diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index fe672e8..9a62cc9 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -17,6 +17,8 @@ "planning", "ai assisted engineering", "sdlc", - "software development lifecyle" + "software development lifecyle", + "claude code", + "github copilot cli" ] } \ No newline at end of file diff --git a/.github/plugin/plugin.json b/.github/plugin/plugin.json new file mode 100644 index 0000000..182d42d --- /dev/null +++ b/.github/plugin/plugin.json @@ -0,0 +1,33 @@ +{ + "name": "vgv-wingspan", + "description": "VGV Wingspan - AI-native workflows following Very Good Ventures best practices.", + "version": "0.0.4", + "author": { + "name": "Very Good Ventures", + "url": "https://verygood.ventures" + }, + "homepage": "https://github.com/VeryGoodOpenSource/vgv-wingspan", + "repository": "https://github.com/VeryGoodOpenSource/vgv-wingspan", + "keywords": [ + "software engineering", + "workflow", + "best practices", + "flow automation", + "code generation", + "planning", + "ai assisted engineering", + "sdlc", + "software development lifecyle", + "claude code", + "github copilot cli" + ], + "skills": "skills", + "agents": [ + "agents/analysis", + "agents/codebase-review", + "agents/quality-review", + "agents/research" + ], + "hooks": "hooks/hooks.json", + "mcpServers": ".mcp.json" +} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 613327f..e895418 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -85,3 +85,66 @@ jobs: run: npm install -g @anthropic-ai/claude-code - name: Validate Plugin run: claude plugin validate . + copilot-manifest: + name: 🐙 Copilot Manifest + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - name: Validate Copilot manifest and metadata parity + run: | + set -euo pipefail + GH=.github/plugin/plugin.json + CC=.claude-plugin/plugin.json + + # 1. Both manifests are valid JSON. + jq empty "$GH" + jq empty "$CC" + + # 2. name is present and kebab-case (Copilot's only hard manifest rule). + NAME=$(jq -r '.name' "$GH") + echo "$NAME" | grep -qE '^[a-z0-9]+(-[a-z0-9]+)*$' \ + || { echo "::error::.github/plugin/plugin.json name '$NAME' is not kebab-case"; exit 1; } + [ "${#NAME}" -le 64 ] || { echo "::error::plugin name exceeds 64 chars"; exit 1; } + + # 3. Shared metadata is identical across both manifests (only the + # Copilot manifest's component-path fields may differ). + if ! diff <(jq -S 'del(.skills,.agents,.hooks,.mcpServers,.commands,.extensions,.lspServers)' "$GH") \ + <(jq -S . "$CC"); then + echo "::error::Metadata drift between .github/plugin/plugin.json and .claude-plugin/plugin.json" + exit 1 + fi + + # 4. Every component path the Copilot manifest declares exists on disk. + for key in skills hooks mcpServers; do + p=$(jq -r --arg k "$key" '.[$k]' "$GH") + [ -e "$p" ] || { echo "::error::$key path '$p' does not exist"; exit 1; } + done + jq -r '.agents[]' "$GH" | while read -r d; do + [ -d "$d" ] || { echo "::error::agents path '$d' does not exist"; exit 1; } + done + echo "Copilot manifest OK: metadata in parity, all component paths present." + copilot-loader: + name: 🐙 Copilot Loader Smoke Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - name: Install GitHub Copilot CLI + # Plugin-management subcommands need no auth or Copilot seat, so this + # smoke test runs on any PR (including forks) with no secrets. Pin the + # version because direct local-path installs are on a deprecation path. + run: npm install -g @github/copilot@1.0.70 + - name: Install plugin and assert every skill loads + run: | + set -euo pipefail + copilot --version + copilot plugin install ./ + copilot skill list --json > skills.json + jq -r '.[] | select(.source=="plugin") | .name' skills.json | sort + # Copilot namespaces a skill to "vgv-wingspan:" only if another + # installed plugin defines the same name; accept either form so the + # check is robust to unrelated plugins in the environment. + for skill in brainstorm plan build quality-review hotfix debrief create create-pr rebase refine-approach plan-technical-review elements-of-style; do + jq -e --arg s "$skill" 'any(.[]; .name == $s or .name == "vgv-wingspan:" + $s)' skills.json >/dev/null \ + || { echo "::error::Copilot did not load the '$skill' skill from the plugin"; exit 1; } + done + echo "All 12 Wingspan skills loaded on Copilot CLI." diff --git a/.release-please-config.json b/.release-please-config.json index 616edf3..c66cfe2 100644 --- a/.release-please-config.json +++ b/.release-please-config.json @@ -23,6 +23,11 @@ "path": ".claude-plugin/plugin.json", "jsonpath": "$.version" }, + { + "type": "json", + "path": ".github/plugin/plugin.json", + "jsonpath": "$.version" + }, { "type": "json", "path": ".claude-plugin/marketplace.json", diff --git a/CLAUDE.md b/CLAUDE.md index 7851ef6..21da771 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # VGV Wingspan -Wingspan is a collection of AI-assisted engineering tools — skills, agents, and hooks — released as a Claude Code plugin. +Wingspan is a collection of AI-assisted engineering tools — skills, agents, and hooks — released as a plugin for both Claude Code and GitHub Copilot CLI. ## Philosophy @@ -22,7 +22,7 @@ The plugin supports three sequential phases: Standalone Skills: -- **`/review`** — Run quality review agents on demand, independent of the build workflow. +- **`/quality-review`** — Run quality review agents on demand, independent of the build workflow. (Named `quality-review`, not `review`, to avoid GitHub Copilot CLI's built-in `/review` command.) - **`/debrief`** — Produce a structured, blameless debrief document after an incident, failed release, or significant bug. @@ -60,12 +60,16 @@ class), and renders one consolidated report plus a matching chat summary (see - `docs/plan/` — Implementation plans from `/plan` - `docs/reviews/` — Consolidated `review.md` + per-agent `raw/` from `/build` (ephemeral, cleaned up by build) - `docs/hotfix-review/` — Consolidated `review.md` + per-agent `raw/` from `/hotfix` (ephemeral, cleaned up by hotfix) -- `docs/code-review/` — One `/` directory per run (`review.md` + per-agent `raw/`) from `/review` (standalone, user-managed) +- `docs/code-review/` — One `/` directory per run (`review.md` + per-agent `raw/`) from `/quality-review` (standalone, user-managed) - `docs/debriefs/` — Debrief documents from `/debrief` +## Host Support + +Wingspan is single-source, dual-host. `.claude-plugin/plugin.json` is the Claude Code manifest; `.github/plugin/plugin.json` is the GitHub Copilot CLI manifest (same metadata, plus explicit `skills`/`agents`/`hooks`/`mcpServers` component paths — Copilot does not discover agents in subdirectories without them). Release tooling bumps both versions. Copilot CLI reads Claude-format hooks, matchers, and `${CLAUDE_PLUGIN_ROOT}` natively, ignores unknown SKILL.md frontmatter, and accepts Claude agent frontmatter (`model: sonnet/haiku/inherit`, `effort`, `skills:`). Skill bodies stay Claude-first but carry short fallbacks where hosts differ: `$ARGUMENTS` substitution, `${CLAUDE_SKILL_DIR}` script paths, `ask_user` as the AskUserQuestion equivalent, and `vgv-wingspan:`-prefixed agent names. The one built-in slash collision on Copilot is `/review`, which is why the standalone review skill is named `quality-review` (its bare name is slash-reachable on both hosts); `/plan` is not a Copilot built-in and works as-is. + ## Hooks -Wingspan uses Claude Code hooks to automate behavior at tool-call boundaries. Hooks are defined in `hooks/hooks.json`. +Wingspan uses hooks to automate behavior at tool-call boundaries. Hooks are defined in `hooks/hooks.json` (Claude Code format — GitHub Copilot CLI executes the same file natively). ### Companion Plugin Recommendations @@ -74,7 +78,7 @@ A `PreToolUse` hook runs on every `Read`, `Glob`, or `Grep` call. It detects the **How it works:** 1. `hooks/recommend-plugins.sh` fires on the first matched tool call and scans every JSON file in `hooks/recommendations/`. Each file declares a detection rule and the plugin to recommend. -2. Every file whose detection rule matches — and whose plugin isn't already installed — is collected. All matching recommendations are emitted together in a single `additionalContext` message. +2. Every file whose detection rule matches — and whose plugin isn't already installed — is collected. All matching recommendations are emitted together in a single `additionalContext` message. The script detects its host (Copilot CLI exports `COPILOT_CLI`/`COPILOT_PLUGIN_ROOT` to hook commands), checks that host's plugin settings (`.claude/` settings files on Claude Code; `~/.copilot` config and `.github/copilot/settings.json` on Copilot), and phrases the install commands for that host. 3. A marker file (`/tmp/wingspan-recommend-plugins-`) is written only when at least one recommendation is emitted, suppressing repeats for the rest of the session. If no plugins are missing, no marker is written and the script re-evaluates on the next tool call — so a newly added recommendation file can still fire later in the same session. **Recommendation file format** (`hooks/recommendations/.json`): @@ -96,7 +100,7 @@ A `PreToolUse` hook runs on every `Read`, `Glob`, or `Grep` call. It detects the | `detect.files` | Shell glob — greps inside every matching file for `pattern` | | `detect.pattern` | Regex grep pattern to confirm the match | | `verificationSkill` | Optional. Skill the `/build` and `/hotfix` ship gate delegates to when this file's `detect` matches and the skill is installed | -| `marketplace` | GitHub `owner/repo` for the marketplace registry | +| `marketplace` | GitHub `owner/repo` for the marketplace registry. Use the canonical repo path — on Copilot CLI the install spec is derived as `@`, which must match the marketplace.json `name` | | `description` | One-line summary shown in the recommendation | **Adding a new recommendation:** Drop a JSON file in `hooks/recommendations/` following the format above. No code changes required. All matching files are evaluated. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3312405..75c97b9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,9 +45,17 @@ After the frontmatter, structure the file as: 2. **Core Standards** — enforced constraints, always first 3. **Content sections** — architecture, code examples, workflows, anti-patterns +**Handling arguments portably.** A skill receives its invocation arguments through the `$ARGUMENTS` token, which Claude Code substitutes wherever it appears in the body. GitHub Copilot CLI does **not** substitute it — the token stays literal. If a skill reads `$ARGUMENTS` (e.g. `$ARGUMENTS`), follow it with this exact fallback line so the skill still works on Copilot: + +```markdown +If the text above still shows a literal placeholder instead of your input (e.g., on GitHub Copilot CLI, which does not substitute it), use whatever the user wrote after the skill name instead. +``` + +As with `${CLAUDE_SKILL_DIR}` (see [Shared scripts](#shared-scripts)), the fallback line must not quote `$ARGUMENTS` itself — Claude Code would substitute the mention and corrupt the sentence. + ### 2. Update `plugin.json` tags -Add relevant keywords to the `keywords` array in `.claude-plugin/plugin.json`. +Add relevant keywords to the `keywords` array in **both** manifests: `.claude-plugin/plugin.json` (Claude Code) and `.github/plugin/plugin.json` (GitHub Copilot CLI). The two files carry the same metadata; only the Copilot manifest additionally declares component paths (`skills`, `agents`, `hooks`, `mcpServers`). ### 3. Update the README skills table @@ -142,6 +150,14 @@ ${CLAUDE_SKILL_DIR}/scripts/detect-base-branch.sh ``` ```` +GitHub Copilot CLI does not substitute `${CLAUDE_SKILL_DIR}`, so whenever a skill body invokes a bundled script this way, follow the code block with this exact fallback line: + +```markdown +If the path above appears unexpanded (e.g., on GitHub Copilot CLI, which does not substitute this variable), run the script from this skill's own `scripts/` directory instead. +``` + +The line must **not** name `${CLAUDE_SKILL_DIR}` (or `$ARGUMENTS`) itself: Claude Code substitutes those tokens everywhere they appear in the body — including inside an explanatory sentence — so a fallback that quotes the token gets corrupted on the very host where the token *does* work. Describe the symptom ("appears unexpanded", "shows a literal placeholder") instead of naming the token. Copilot's plugin installer dereferences the symlinks into real files, so the relative `scripts/` path always resolves. + Keep scripts executable (`chmod +x`) so they can be invoked directly without a `bash` wrapper. Avoid the fenced `` ```! `` auto-execute form — under stricter permission checks (Claude Code v2.1.98+) it passes the literal block content (including the `!` prefix) to the permission matcher, which no longer aligns with a `Bash()` pattern. ### When to use scripts vs inline bash @@ -241,6 +257,25 @@ Then, inside a session: /plugin install vgv-wingspan ``` +### Test on GitHub Copilot CLI + +Wingspan also runs as a [Copilot CLI plugin](https://docs.github.com/copilot/concepts/agents/copilot-cli/about-cli-plugins) via the `.github/plugin/plugin.json` manifest. To exercise your working copy there: + +```bash +copilot plugin install ./ # from the repo root; reinstall after every edit (components are cached) +copilot plugin list # confirm vgv-wingspan appears +``` + +Then, in an interactive `copilot` session: + +| Component | How to verify | +| --------- | ------------- | +| **Skills** | `/skills list` — Wingspan skills appear under their bare names (no `vgv-wingspan:` prefix). | +| **Agents** | `/agent` — plugin agents appear as `vgv-wingspan:`. | +| **Hooks** | Same as Claude Code: `Read` a file in a detectable project and watch for the recommendation. The same `/tmp/wingspan-recommend-plugins-*` marker applies. | + +When finished: `copilot plugin uninstall vgv-wingspan`. Note that Copilot CLI reads Claude-format hooks and matchers natively, exports `${CLAUDE_PLUGIN_ROOT}` to hook commands, and ignores unknown SKILL.md frontmatter — so most changes need no Copilot-specific work. One naming rule to keep: Copilot ships a built-in `/review` command, so the standalone review skill is named `quality-review` to stay slash-reachable. If you add a skill, avoid Copilot's built-in command names (`/review` is the one that currently affects Wingspan; `/plan` is **not** a built-in and is fine). + ### Validate before you push Run the same check CI runs, from the repository root: diff --git a/README.md b/README.md index 60b906a..dc7fe90 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Very Good Ventures][logo_white]][very_good_ventures_link_dark] [![Very Good Ventures][logo_black]][very_good_ventures_link_light] -🦋 AI-assisted workflows that follow [Very Good Ventures][vgv_link] best practices and standards. +🦋 AI-assisted workflows that follow [Very Good Ventures][vgv_link] best practices and standards. Runs as a plugin on both **Claude Code** and **GitHub Copilot CLI**. Developed with 💙 by [Very Good Ventures][vgv_link] 🦄 @@ -11,7 +11,7 @@ Developed with 💙 by [Very Good Ventures][vgv_link] 🦄 ## Installation -### From the Marketplace +### Claude Code One-line install from your terminal: @@ -33,6 +33,17 @@ Or inside an active Claude Code session, run these as **two separate commands** /plugin install vgv-wingspan ``` +### GitHub Copilot CLI + +The same marketplace works on [GitHub Copilot CLI](https://docs.github.com/copilot/concepts/agents/copilot-cli/about-copilot-cli) (v1.0.64 or later recommended). From your terminal: + +```bash +copilot plugin marketplace add VeryGoodOpenSource/very-good-claude-code-marketplace +copilot plugin install vgv-wingspan@very-good-claude-code-marketplace +``` + +Skills, agents, the recommendation hook, and the bundled MCP server all load on Copilot CLI, and every skill is invocable as a slash command (`/brainstorm`, `/plan`, `/build`, `/hotfix`, …). The standalone review skill is named **`/quality-review`** on both hosts, because Copilot ships its own built-in `/review` command — so the Wingspan review runs as `/quality-review`. + ## Getting Started Wingspan follows a four-phase workflow: **brainstorm**, **plan**, **build**, and **review**. Each phase produces artifacts that feed into the next, so you can clear context between steps without losing work. You can invoke skills explicitly with slash commands or let them activate automatically from natural language — just describe what you need and the right skill will trigger. @@ -65,16 +76,18 @@ Execute the plan — write code, write tests, run quality review, and open a PR: /build docs/plan/add-authentication.md ``` -### 4. `/review` +### 4. `/quality-review` Runs specialized agents in parallel — VGV standards, architecture, test quality, and simplicity. Findings land in one consolidated report with stable `FINDING-NN` ids, and the chat summary mirrors it so you can act on any finding by number. Catches issues before they reach PR. As simple as this: ```text -/review +/quality-review ``` +(Named `/quality-review` rather than `/review` so it works as a slash command on GitHub Copilot CLI, whose built-in `/review` would otherwise shadow it.) + ## Better Together: Working With The Very Good AI Flutter Plugin Wingspan and the [Very Good AI Flutter Plugin](https://github.com/VeryGoodOpenSource/very_good_ai_flutter_plugin) are designed as complementary layers of VGV's AI-assisted engineering stack. The Flutter Plugin embeds battle-tested best practices — architecture patterns, accessibility, testing, performance, and security — directly into Claude Code, so AI-generated code follows VGV's production-quality standards from the first line. @@ -96,7 +109,7 @@ Wingspan operates at a higher level, orchestrating agentic workflows across the | [**Plan**](skills/plan/SKILL.md) | `/plan ` | Transform brainstorm output into a reviewed, phased implementation plan | | [**Plan Technical Review**](skills/plan-technical-review/SKILL.md) | `/plan-technical-review ` | Review an externally-authored plan — plans from `/plan` are already reviewed during creation | | [**Build**](skills/build/SKILL.md) | `/build ` | Execute a plan — write code and tests, run quality review, ship a PR | -| [**Review**](skills/review/SKILL.md) | `/review [path]` | Run quality review agents on demand — assess code quality and identify issues | +| [**Quality Review**](skills/quality-review/SKILL.md) | `/quality-review [path]` | Run quality review agents on demand — assess code quality and identify issues | | [**Hotfix**](skills/hotfix/SKILL.md) | `/hotfix ` | Apply a minimal, targeted fix for emergency bugs — enforces review and testing without brainstorm or planning | | [**Create**](skills/create/SKILL.md) | `/create ` | Scaffold a new project by routing to the right companion plugin | | [**Create PR**](skills/create-pr/SKILL.md) | `/create-pr` | Validate (formatter, linter, tests, and CI checks), stage, commit, push, and open a pull request on the project's Git hosting platform — aborts on any failure | @@ -105,7 +118,7 @@ Wingspan operates at a higher level, orchestrating agentic workflows across the ## Agents -Wingspan ships subagents that Claude Code dispatches as isolated, specialized reviewers. Unlike skills, agents are **not** invoked as slash commands — the workflow skills dispatch them automatically, or you can ask Claude to run one by name (e.g. "review my changes with the vgv-review-agent"). +Wingspan ships subagents that the host dispatches as isolated, specialized reviewers. Unlike skills, agents are **not** invoked as slash commands — the workflow skills dispatch them automatically, or you can ask by name (e.g. "review my changes with the vgv-review-agent"). On GitHub Copilot CLI they appear namespaced as `vgv-wingspan:` in the `/agent` picker. | Agent | Description | | ----- | ----------- | @@ -122,7 +135,7 @@ Wingspan ships subagents that Claude Code dispatches as isolated, specialized re ## Hooks -Wingspan includes a `PreToolUse` hook that detects your project type and recommends companion plugins you haven't installed yet. +Wingspan includes a `PreToolUse` hook that detects your project type and recommends companion plugins you haven't installed yet. It runs on both Claude Code and GitHub Copilot CLI, and tailors its install instructions to the host it is running on. | Hook | Trigger | Behavior | | ---- | ------- | -------- | diff --git a/agents/codebase-review/code-simplicity-review-agent.md b/agents/codebase-review/code-simplicity-review-agent.md index ac9c3b6..9c1ead2 100644 --- a/agents/codebase-review/code-simplicity-review-agent.md +++ b/agents/codebase-review/code-simplicity-review-agent.md @@ -40,7 +40,7 @@ You are a code simplicity expert specializing in minimalism and the YAGNI (You A ## Phase 0 — Detect stack and discover conventions -Before reviewing, read the project's CLAUDE.md, dependency manifests, and directory structure to detect the tech stack. Then discover companion-plugin conventions: scan your available-skills list for technology-specific skills whose descriptions match the code under review and load the relevant ones with the Skill tool (only skills that appear in your list — never guess names); also glob project-local skills the plugin system does not manage (`.claude/skills/**/SKILL.md`), reading the frontmatter and then the full content of any whose domain matches. A pattern a companion plugin documents as idiomatic is a convention, not a simplification target — do not flag it. If neither yields anything, proceed with VGV defaults; this step is best-effort and must never block the review. +Before reviewing, read the project's CLAUDE.md, dependency manifests, and directory structure to detect the tech stack. Then discover companion-plugin conventions: scan your available-skills list for technology-specific skills whose descriptions match the code under review and load the relevant ones with the Skill tool (only skills that appear in your list — never guess names); also glob project-local skills the plugin system does not manage (`.claude/skills/**/SKILL.md`, `.github/skills/**/SKILL.md`, `.agents/skills/**/SKILL.md`), reading the frontmatter and then the full content of any whose domain matches. A pattern a companion plugin documents as idiomatic is a convention, not a simplification target — do not flag it. If neither yields anything, proceed with VGV defaults; this step is best-effort and must never block the review. When reviewing code, you will: diff --git a/agents/codebase-review/codebase-review-agent.md b/agents/codebase-review/codebase-review-agent.md index 4878b00..fd425bd 100644 --- a/agents/codebase-review/codebase-review-agent.md +++ b/agents/codebase-review/codebase-review-agent.md @@ -42,7 +42,7 @@ Your role is to conduct a thorough review of the given codebase, ensure code qua ## Phase 0 — Detect stack and discover conventions -Before reviewing, detect the project's tech stack: read the project's CLAUDE.md, dependency manifests, linting configuration, and directory structure to determine the tools and frameworks in use. Then discover companion-plugin conventions: scan your available-skills list for technology-specific skills whose descriptions match the codebase and load the relevant ones with the Skill tool (only skills that appear in your list — never guess names); also glob project-local skills the plugin system does not manage (`.claude/skills/**/SKILL.md`), reading the frontmatter and then the full content of any whose domain matches. Apply their documented patterns as project conventions, layered on top of VGV standards. If neither yields anything, proceed with VGV defaults; this step is best-effort and must never block the review. +Before reviewing, detect the project's tech stack: read the project's CLAUDE.md, dependency manifests, linting configuration, and directory structure to determine the tools and frameworks in use. Then discover companion-plugin conventions: scan your available-skills list for technology-specific skills whose descriptions match the codebase and load the relevant ones with the Skill tool (only skills that appear in your list — never guess names); also glob project-local skills the plugin system does not manage (`.claude/skills/**/SKILL.md`, `.github/skills/**/SKILL.md`, `.agents/skills/**/SKILL.md`), reading the frontmatter and then the full content of any whose domain matches. Apply their documented patterns as project conventions, layered on top of VGV standards. If neither yields anything, proceed with VGV defaults; this step is best-effort and must never block the review. When reviewing the codebase, you will review: diff --git a/agents/codebase-review/vgv-review-agent.md b/agents/codebase-review/vgv-review-agent.md index 123f31b..899de25 100644 --- a/agents/codebase-review/vgv-review-agent.md +++ b/agents/codebase-review/vgv-review-agent.md @@ -50,7 +50,7 @@ You are an expert software engineer at Very Good Ventures performing a rigorous **Then discover companion-plugin conventions.** Installed companion plugins ship technology-specific skills (state management, testing, layered architecture, navigation, and more) that extend VGV's defaults. Find and apply them: 1. **Check your available skills.** Installed plugins expose their skills to you directly — scan your available-skills list for ones whose descriptions match the code under review, and load the relevant ones with the Skill tool. Only invoke skills that appear in your list; never guess names. -2. **Glob project-local skills** the plugin system does not manage: `.claude/skills/**/SKILL.md`. Read each match's frontmatter (`name`, `description`) and the full content of any whose domain matches. +2. **Glob project-local skills** the plugin system does not manage: `.claude/skills/**/SKILL.md`, `.github/skills/**/SKILL.md`, and `.agents/skills/**/SKILL.md`. Read each match's frontmatter (`name`, `description`) and the full content of any whose domain matches. 3. Enforce the documented patterns from both as project conventions, layered on top of VGV standards. If neither yields anything, proceed with VGV defaults — this step is best-effort and must never block the review. diff --git a/agents/quality-review/architecture-review-agent.md b/agents/quality-review/architecture-review-agent.md index beecfda..bb085df 100644 --- a/agents/quality-review/architecture-review-agent.md +++ b/agents/quality-review/architecture-review-agent.md @@ -42,7 +42,7 @@ You are a software architecture expert at Very Good Ventures. Your role is to va **Then discover companion-plugin conventions.** Installed companion plugins ship technology-specific skills (layered architecture, state management, dependency boundaries, and more) that extend VGV's defaults. Find and apply them: 1. **Check your available skills.** Installed plugins expose their skills to you directly — scan your available-skills list for ones whose descriptions match the code under review, and load the relevant ones with the Skill tool. Only invoke skills that appear in your list; never guess names. -2. **Glob project-local skills** the plugin system does not manage: `.claude/skills/**/SKILL.md`. Read each match's frontmatter (`name`, `description`) and the full content of any whose domain matches. +2. **Glob project-local skills** the plugin system does not manage: `.claude/skills/**/SKILL.md`, `.github/skills/**/SKILL.md`, and `.agents/skills/**/SKILL.md`. Read each match's frontmatter (`name`, `description`) and the full content of any whose domain matches. 3. Enforce the documented patterns from both as project conventions, layered on top of VGV standards. If neither yields anything, proceed with VGV defaults — this step is best-effort and must never block the review. diff --git a/agents/quality-review/test-quality-review-agent.md b/agents/quality-review/test-quality-review-agent.md index 264d912..da92a58 100644 --- a/agents/quality-review/test-quality-review-agent.md +++ b/agents/quality-review/test-quality-review-agent.md @@ -42,7 +42,7 @@ You are a testing expert at Very Good Ventures. Your mission is to ensure every **Then discover companion-plugin conventions.** Installed companion plugins ship technology-specific skills (testing frameworks, mocking, golden/widget tests, and more) that extend VGV's defaults. Find and apply them: 1. **Check your available skills.** Installed plugins expose their skills to you directly — scan your available-skills list for ones whose descriptions match the tests under review, and load the relevant ones with the Skill tool. Only invoke skills that appear in your list; never guess names. -2. **Glob project-local skills** the plugin system does not manage: `.claude/skills/**/SKILL.md`. Read each match's frontmatter (`name`, `description`) and the full content of any whose domain matches. +2. **Glob project-local skills** the plugin system does not manage: `.claude/skills/**/SKILL.md`, `.github/skills/**/SKILL.md`, and `.agents/skills/**/SKILL.md`. Read each match's frontmatter (`name`, `description`) and the full content of any whose domain matches. 3. Enforce the documented patterns from both as project conventions, layered on top of VGV standards. If neither yields anything, proceed with VGV defaults — this step is best-effort and must never block the review. diff --git a/agents/research/best-practices-research-agent.md b/agents/research/best-practices-research-agent.md index d1ed820..5bc787a 100644 --- a/agents/research/best-practices-research-agent.md +++ b/agents/research/best-practices-research-agent.md @@ -17,8 +17,8 @@ Your mission is to provide comprehensive, actionable guidance based on establish Before doing any external research, check that local knowledge might exist: 1. **Discover Available Skills**: - - Use Glob to find all SKILL.md files: `**/**/SKILL.md` and `~/.claude/skills/**/SKILL.md` - - Also check project-level skills: `.claude/skills/**/SKILL.md` + - Use Glob to find all SKILL.md files: `**/**/SKILL.md`, plus the host's personal skill dirs (`~/.claude/skills/**/SKILL.md`, `~/.copilot/skills/**/SKILL.md`, `~/.agents/skills/**/SKILL.md`) + - Also check project-level skills: `.claude/skills/**/SKILL.md`, `.github/skills/**/SKILL.md`, and `.agents/skills/**/SKILL.md` - Read the skill descriptions to understand what each covers 2. **Extract Patterns from Skills**: diff --git a/hooks/recommend-plugins.sh b/hooks/recommend-plugins.sh index 069838c..c7bd85d 100755 --- a/hooks/recommend-plugins.sh +++ b/hooks/recommend-plugins.sh @@ -1,9 +1,14 @@ #!/bin/bash # PreToolUse hook: recommend companion plugins based on project type. # +# Runs on both Claude Code and GitHub Copilot CLI — both hosts execute +# Claude-format plugin hooks and accept the hookSpecificOutput JSON emitted +# on stdout. Copilot CLI exports COPILOT_CLI/COPILOT_PLUGIN_ROOT to hook +# commands, which is how the script tells the hosts apart. +# # Scans JSON files in the recommendations/ directory. Each file describes # a plugin to recommend: how to detect the project type (a file + grep -# pattern) and the plugin name to look for in Claude Code settings. +# pattern) and the plugin name to look for in the host's plugin settings. # # To add a new recommendation, drop a JSON file in recommendations/ with: # { @@ -29,9 +34,26 @@ INPUT=$(cat) +# Resolve the user's project directory and run from there. Claude Code runs +# hook commands with cwd already at the project; Copilot CLI runs plugin hooks +# with cwd at the plugin root, so rely on the project-dir env var either host +# provides before falling back to $PWD. +PROJECT_DIR="${CLAUDE_PROJECT_DIR:-${COPILOT_PROJECT_DIR:-$PWD}}" +cd "$PROJECT_DIR" 2>/dev/null || exit 0 + +# Detect the host. Copilot CLI sets COPILOT_CLI/COPILOT_PLUGIN_ROOT for hook +# commands; Claude Code sets neither. +if [[ -n "${COPILOT_CLI:-}" || -n "${COPILOT_PLUGIN_ROOT:-}" ]]; then + HOST="copilot" +else + HOST="claude" +fi + # Skip if we already ran recommendations for this project in this session. +# The marker is host-scoped so a run on one host does not suppress the +# host-tailored recommendation on the other for the same project. PROJECT_HASH=$(echo "$PWD" | shasum | cut -d' ' -f1) -MARKER="/tmp/wingspan-recommend-plugins-$PROJECT_HASH" +MARKER="/tmp/wingspan-recommend-plugins-$HOST-$PROJECT_HASH" if [[ -f "$MARKER" ]]; then exit 0 @@ -44,16 +66,34 @@ if [[ ! -d "$RECOMMENDATIONS_DIR" ]]; then exit 0 fi -# Collect settings files to check (local > project > user). -SETTINGS_FILES=( +# Files that record installed/enabled plugins, per host (most specific first). +CLAUDE_SETTINGS_FILES=( ".claude/settings.local.json" ".claude/settings.json" "$HOME/.claude/settings.json" ) +COPILOT_DIR="${COPILOT_HOME:-$HOME/.copilot}" +COPILOT_SETTINGS_FILES=( + ".github/copilot/settings.json" + "$COPILOT_DIR/settings.json" + "$COPILOT_DIR/config.json" +) is_plugin_installed() { local plugin_name="$1" - for settings_file in "${SETTINGS_FILES[@]}"; do + # On Copilot, the authoritative signal is an installed-plugin directory + # (~/.copilot/installed-plugins//); check it before + # falling back to grepping the settings/config files for the enabled flag. + if [[ "$HOST" == "copilot" ]]; then + for plugin_dir in "$COPILOT_DIR"/installed-plugins/*/"$plugin_name"; do + [[ -d "$plugin_dir" ]] && return 0 + done + fi + local settings_files=("${CLAUDE_SETTINGS_FILES[@]}") + if [[ "$HOST" == "copilot" ]]; then + settings_files=("${COPILOT_SETTINGS_FILES[@]}") + fi + for settings_file in "${settings_files[@]}"; do if [[ -f "$settings_file" ]] && grep -q "$plugin_name" "$settings_file" 2>/dev/null; then return 0 fi @@ -61,6 +101,22 @@ is_plugin_installed() { return 1 } +# Compose the host-appropriate recommendation message. Both hosts support the +# in-session /plugin commands; Copilot CLI installs marketplace plugins as +# @, where the marketplace name defaults to the +# repository name. +recommendation_message() { + local plugin="$1" + local marketplace="$2" + local description="$3" + if [[ "$HOST" == "copilot" ]]; then + local marketplace_name="${marketplace##*/}" + echo "The '${plugin}' Copilot CLI plugin is not installed. It provides: ${description} Recommend the user install it by first adding the marketplace with: copilot plugin marketplace add ${marketplace} — then installing via: copilot plugin install ${plugin}@${marketplace_name}" + else + echo "The '${plugin}' Claude Code plugin is not installed. It provides: ${description} Recommend the user install it by first adding the marketplace with: /plugin marketplace add ${marketplace} — then installing via: /plugin install ${plugin}" + fi +} + # Evaluate each recommendation file and collect all matches. RECOMMENDATIONS=() @@ -113,7 +169,7 @@ for rec_file in "$RECOMMENDATIONS_DIR"/*.json; do fi # Collect recommendation - RECOMMENDATIONS+=("The '${plugin}' Claude Code plugin is not installed. It provides: ${description} Recommend the user install it by first adding the marketplace with: /plugin marketplace add ${marketplace} — then installing via: /plugin install ${plugin}") + RECOMMENDATIONS+=("$(recommendation_message "$plugin" "$marketplace" "$description")") done # Emit all recommendations in a single message, then set the marker. diff --git a/hooks/recommendations/very-good-ai-flutter-plugin.json b/hooks/recommendations/vgv-ai-flutter-plugin.json similarity index 69% rename from hooks/recommendations/very-good-ai-flutter-plugin.json rename to hooks/recommendations/vgv-ai-flutter-plugin.json index 8806c4f..b831e77 100644 --- a/hooks/recommendations/very-good-ai-flutter-plugin.json +++ b/hooks/recommendations/vgv-ai-flutter-plugin.json @@ -1,11 +1,11 @@ { - "plugin": "very-good-ai-flutter-plugin", + "plugin": "vgv-ai-flutter-plugin", "detect": [ { "file": "pubspec.yaml", "pattern": "." }, { "files": "docs/plan/*.md", "pattern": "flutter|dart" }, { "files": "docs/brainstorm/*.md", "pattern": "flutter|dart" } ], - "verificationSkill": "very-good-ai-flutter-plugin:green-gate", - "marketplace": "VeryGoodOpenSource/very_good_claude_code_marketplace", + "verificationSkill": "vgv-ai-flutter-plugin:green-gate", + "marketplace": "VeryGoodOpenSource/very-good-claude-code-marketplace", "description": "Dart and Flutter best-practice skills (accessibility, BLoC, testing, theming, navigation, security, i18n, architecture) and automated dart analyze/format hooks." } diff --git a/hooks/test_recommend_plugins.sh b/hooks/test_recommend_plugins.sh index 65df530..5df7960 100644 --- a/hooks/test_recommend_plugins.sh +++ b/hooks/test_recommend_plugins.sh @@ -34,21 +34,35 @@ setup() { ORIGINAL_HOME="$HOME" export HOME="$TEST_DIR" - # Ensure no stale marker exists for this test dir. + # Ensure no stale marker exists for this test dir. Markers are host-scoped, + # so track both variants. MARKER is the claude-host marker (run_hook writes + # it); COPILOT_MARKER is written by run_hook_copilot. PROJECT_HASH=$(echo "$TEST_DIR" | shasum | cut -d' ' -f1) - MARKER="/tmp/wingspan-recommend-plugins-$PROJECT_HASH" - rm -f "$MARKER" + MARKER="/tmp/wingspan-recommend-plugins-claude-$PROJECT_HASH" + COPILOT_MARKER="/tmp/wingspan-recommend-plugins-copilot-$PROJECT_HASH" + rm -f "$MARKER" "$COPILOT_MARKER" } teardown() { export HOME="$ORIGINAL_HOME" - rm -f "$MARKER" 2>/dev/null || true + rm -f "$MARKER" "$COPILOT_MARKER" 2>/dev/null || true rm -rf "$TEST_DIR" 2>/dev/null || true } # Run the hook from the test project directory. Captures stdout. +# Copilot and project-dir env vars are stripped so the script sees a Claude +# Code host rooted at the test dir even when the test suite itself runs under +# another host. run_hook() { - echo '{}' | (cd "$TEST_DIR" && bash "$WRAPPER") 2>/dev/null || true + echo '{}' | (cd "$TEST_DIR" && env -u COPILOT_CLI -u COPILOT_PLUGIN_ROOT -u COPILOT_HOME -u CLAUDE_PROJECT_DIR -u COPILOT_PROJECT_DIR bash "$WRAPPER") 2>/dev/null || true +} + +# Run the hook simulating a GitHub Copilot CLI host: cwd is NOT the project +# (Copilot runs plugin hooks from the plugin root) — the script must find the +# project via COPILOT_PROJECT_DIR. COPILOT_HOME points inside the test dir so +# user-level Copilot settings are controlled fixtures. +run_hook_copilot() { + echo '{}' | (cd / && env -u CLAUDE_PROJECT_DIR COPILOT_CLI=1 COPILOT_PROJECT_DIR="$TEST_DIR" COPILOT_HOME="$TEST_DIR/.copilot" bash "$WRAPPER") 2>/dev/null || true } # Add a recommendation JSON file to the test fixtures. @@ -508,6 +522,119 @@ test_files_detection_is_case_insensitive() { teardown } +test_copilot_host_message() { + echo "test: Copilot CLI host gets copilot-flavored install instructions" + setup + add_recommendation "test-plugin" '{ + "plugin": "test-plugin", + "detect": { "file": "pubspec.yaml", "pattern": "." }, + "marketplace": "Org/my-marketplace", + "description": "Test plugin." + }' + add_project_file "pubspec.yaml" "name: my_app" + local output + output=$(run_hook_copilot) + assert_contains "$output" "Copilot CLI plugin" "names the Copilot CLI plugin" + assert_contains "$output" "copilot plugin marketplace add Org/my-marketplace" "copilot marketplace add command" + assert_contains "$output" "copilot plugin install test-plugin@my-marketplace" "copilot install command with marketplace name" + assert_not_contains "$output" "Claude Code plugin" "no Claude phrasing on Copilot host" + assert_contains "$output" "hookSpecificOutput" "same hook output envelope on Copilot" + teardown +} + +test_copilot_installed_user_config() { + echo "test: Copilot host skips plugin present in Copilot user config" + setup + add_recommendation "test-plugin" '{ + "plugin": "test-plugin", + "detect": { "file": "pubspec.yaml", "pattern": "." }, + "marketplace": "Org/repo", + "description": "Test plugin." + }' + add_project_file "pubspec.yaml" "name: my_app" + mkdir -p "$TEST_DIR/.copilot" + echo '{"installedPlugins": [{"name": "test-plugin"}]}' > "$TEST_DIR/.copilot/config.json" + local output + output=$(run_hook_copilot) + assert_empty "$output" "no output when plugin in Copilot config.json" + assert_file_not_exists "$COPILOT_MARKER" "no marker written" + teardown +} + +test_copilot_installed_repo_settings() { + echo "test: Copilot host skips plugin enabled in repo Copilot settings" + setup + add_recommendation "test-plugin" '{ + "plugin": "test-plugin", + "detect": { "file": "pubspec.yaml", "pattern": "." }, + "marketplace": "Org/repo", + "description": "Test plugin." + }' + add_project_file "pubspec.yaml" "name: my_app" + add_project_file ".github/copilot/settings.json" '{"enabledPlugins": {"test-plugin@my-marketplace": true}}' + local output + output=$(run_hook_copilot) + assert_empty "$output" "no output when plugin in repo Copilot settings" + assert_file_not_exists "$COPILOT_MARKER" "no marker written" + teardown +} + +test_copilot_ignores_claude_settings() { + echo "test: Copilot host still recommends a plugin only installed on Claude Code" + setup + add_recommendation "test-plugin" '{ + "plugin": "test-plugin", + "detect": { "file": "pubspec.yaml", "pattern": "." }, + "marketplace": "Org/repo", + "description": "Test plugin." + }' + add_project_file "pubspec.yaml" "name: my_app" + add_settings ".claude/settings.json" '{"plugins": ["test-plugin"]}' + local output + output=$(run_hook_copilot) + assert_contains "$output" "test-plugin" "Claude-only install does not satisfy Copilot host" + teardown +} + +test_copilot_installed_plugin_dir() { + echo "test: Copilot host skips plugin present as an installed-plugins directory" + setup + add_recommendation "test-plugin" '{ + "plugin": "test-plugin", + "detect": { "file": "pubspec.yaml", "pattern": "." }, + "marketplace": "Org/repo", + "description": "Test plugin." + }' + add_project_file "pubspec.yaml" "name: my_app" + mkdir -p "$TEST_DIR/.copilot/installed-plugins/some-marketplace/test-plugin" + local output + output=$(run_hook_copilot) + assert_empty "$output" "no output when plugin dir exists under installed-plugins" + teardown +} + +test_marker_is_host_scoped() { + echo "test: a Claude run does not suppress the Copilot recommendation (host-scoped marker)" + setup + add_recommendation "test-plugin" '{ + "plugin": "test-plugin", + "detect": { "file": "pubspec.yaml", "pattern": "." }, + "marketplace": "Org/repo", + "description": "Test plugin." + }' + add_project_file "pubspec.yaml" "name: my_app" + # First run as Claude Code — writes the claude-scoped marker. + run_hook > /dev/null + assert_file_exists "$MARKER" "claude marker created" + assert_file_not_exists "$COPILOT_MARKER" "copilot marker not created by claude run" + # A Copilot run on the same project must still emit — its marker is separate. + local output + output=$(run_hook_copilot) + assert_contains "$output" "Copilot CLI plugin" "copilot run still recommends after claude run" + assert_file_exists "$COPILOT_MARKER" "copilot marker created" + teardown +} + # --------------------------------------------------------------------------- # Run all tests # --------------------------------------------------------------------------- @@ -553,6 +680,18 @@ test_file_detection_is_case_insensitive echo "" test_files_detection_is_case_insensitive echo "" +test_copilot_host_message +echo "" +test_copilot_installed_user_config +echo "" +test_copilot_installed_repo_settings +echo "" +test_copilot_ignores_claude_settings +echo "" +test_copilot_installed_plugin_dir +echo "" +test_marker_is_host_scoped +echo "" echo "=== Results: $PASS passed, $FAIL failed ===" if [[ $FAIL -gt 0 ]]; then diff --git a/skills/brainstorm/SKILL.md b/skills/brainstorm/SKILL.md index a750ac9..bddc428 100644 --- a/skills/brainstorm/SKILL.md +++ b/skills/brainstorm/SKILL.md @@ -4,7 +4,7 @@ user-invocable: true description: Explores requirements and approaches through collaborative dialogue before planning implementation. when_to_use: Use when user says "brainstorm", "explore idea", "what should we build", "think through this", or "let's discuss approaches". argument-hint: feature or idea to explore -compatibility: Designed for Claude Code (or similar products with agent support) +compatibility: Designed for Claude Code and GitHub Copilot CLI (or similar products with agent support) --- # Brainstorm a feature or improvement @@ -15,6 +15,8 @@ Clarify **WHAT** to build before diving into **HOW** to build it. Explore user i $ARGUMENTS +If the text above still shows a literal placeholder instead of your input (e.g., on GitHub Copilot CLI, which does not substitute it), use whatever the user wrote after the skill name instead. + **If the feature description above is empty, ask the user**: "What feature would you like to brainstorm? Describe the idea, problem or feature you are thinking about." DO NOT proceed until you have a description from the user. @@ -30,7 +32,7 @@ Determine whether this is a **new project** or a **feature for the current proje | User says "new app", "new project", "build from scratch"; no relevant code in working directory | New project | | User references existing code/screens; idea extends current functionality | Feature for current project → skip to Step 0.1 | -**If new project**, use **AskUserQuestion**: "This sounds like a new project. Where would you like to work?" +**If new project**, use **AskUserQuestion** (GitHub Copilot CLI: `ask_user`): "This sounds like a new project. Where would you like to work?" 1. **Create project first (Recommended)** — output instructions to run `/create`, open the new folder, then `/brainstorm ` in that workspace. Then stop. 2. **Continue here** — proceed to Step 0.1 @@ -54,6 +56,8 @@ Run a quick project review to understand existing patterns: - Task @codebase-review-agent("Understand existing patterns related to: ") +On GitHub Copilot CLI, plugin agents are listed with a `vgv-wingspan:` prefix — match by name suffix. + Focus on: similar features, established patterns, CLAUDE.md guidance. #### 1.2. Collaborative conversation diff --git a/skills/build/SKILL.md b/skills/build/SKILL.md index c0edb49..fb94104 100644 --- a/skills/build/SKILL.md +++ b/skills/build/SKILL.md @@ -6,7 +6,7 @@ when_to_use: Use when user says "build this", "implement the plan", "start codin effort: high argument-hint: plan file path allowed-tools: Bash(rm -rf docs/reviews/) -compatibility: Designed for Claude Code (or similar products with agent support) +compatibility: Designed for Claude Code and GitHub Copilot CLI (or similar products with agent support) --- # Execute an implementation plan @@ -30,6 +30,8 @@ Build Progress: $ARGUMENTS +If the text above still shows a literal placeholder instead of your input (e.g., on GitHub Copilot CLI, which does not substitute it), use whatever the user wrote after the skill name instead. + ## Phase 0 — Load Plan ```bash @@ -47,12 +49,12 @@ Do not proceed without a plan. **After loading the plan:** parse title, type, the `success-criteria` block, tasks, file paths, and the `## Implementation Phases` section if present. -**Commit autonomy:** decide once how this build commits, and carry the choice through the whole run. Honor a saved preference if one exists (Claude memory or the user's personal settings); otherwise use **AskUserQuestion**: +**Commit autonomy:** decide once how this build commits, and carry the choice through the whole run. Honor a saved preference if one exists (Claude memory or the user's personal settings); otherwise use **AskUserQuestion** (GitHub Copilot CLI: `ask_user`): - **Auto-commit each phase (Recommended)**: commit automatically as each phase completes. Pushing and opening the PR still pause for approval (Phase 4). - **I'll commit myself**: build one phase, then stop so the user reviews and commits. Nothing is committed or pushed without the user. -Offer to save the choice to Claude memory (a personal preference) so future builds skip this question. Save it as the user's own preference — never write it to the project's CLAUDE.md, since committing this is a per-developer choice, not a repo convention. +Offer to save the choice to personal memory (e.g., Claude memory) so future builds skip this question — skip the offer on hosts with no memory feature. Save it as the user's own preference — never write it to the project's CLAUDE.md, since committing this is a per-developer choice, not a repo convention. **Resuming a phased build:** if the plan has an `## Implementation Phases` section with at least one phase already marked `**Status:** Done`, this is a resumed build. Announce "Resuming at Phase N: [name]" — the first phase whose status is not `Done` — and go straight to Phase 1 for that phase. Skip the scope-confirmation question below. @@ -169,6 +171,9 @@ The 5 agents and their report names (``): | **@code-simplicity-review-agent** | `code-simplicity-review` | | **@pr-readiness-review-agent** | `pr-readiness-review` | +On GitHub Copilot CLI these agents are installed by the `vgv-wingspan` plugin and are +listed with a `vgv-wingspan:` prefix — match agents by name suffix. + If an agent fails, note it, continue with the rest, and record the failure in the report header. ### After all reviews complete @@ -223,7 +228,7 @@ Whatever commits this build produced are local. Pushing and opening a PR is outw - **No such preference** → use **AskUserQuestion** before anything leaves the machine: 1. **Review locally first (Recommended)**: stop here. The commits stay local; the user pushes and opens the PR when ready. Do not call `/create-pr`. 2. **Push and open the PR now**: proceed this once. - 3. **Always push automatically**: proceed, and save the preference to Claude memory (the user's own preference, never the project's CLAUDE.md) so future builds skip this prompt. + 3. **Always push automatically**: proceed, and save the preference to personal memory (the user's own preference, never the project's CLAUDE.md; skip saving on hosts with no memory feature) so future builds skip this prompt. To push, call `/create-pr skip-checks` — it pushes and opens the PR. Validation already ran above. The PR body uses the [PR template](references/pr-template.md). diff --git a/skills/create-pr/SKILL.md b/skills/create-pr/SKILL.md index cadee17..8b5b396 100644 --- a/skills/create-pr/SKILL.md +++ b/skills/create-pr/SKILL.md @@ -5,7 +5,7 @@ when_to_use: Use when user says "create a PR", "open a PR", "ship it", "submit a argument-hint: "[optional: skip-checks | ticket/issue number e.g. VGV-123 | short description]" disable-model-invocation: true allowed-tools: Bash(git push *) Bash(git add *) Bash(git commit *) Bash(gh *) Bash(glab *) -compatibility: Designed for Claude Code (or similar products with git access) +compatibility: Designed for Claude Code and GitHub Copilot CLI (or similar products with git access) --- # Create a pull request @@ -31,7 +31,7 @@ Stage uncommitted changes, commit them, push the branch, and open a pull request $ARGUMENTS -This may include `skip-checks`, a ticket number (e.g. `VGV-123`), a short description, or be empty. +This may include `skip-checks`, a ticket number (e.g. `VGV-123`), a short description, or be empty. If the text above still shows a literal placeholder instead of your input (e.g., on GitHub Copilot CLI, which does not substitute it), use whatever the user wrote after the skill name instead. ## Step 0: Parse arguments @@ -65,7 +65,7 @@ git diff ### Determine base branch -Use **AskUserQuestion**: +Use **AskUserQuestion** (GitHub Copilot CLI: `ask_user`): **Question:** "Which branch should this PR target?" diff --git a/skills/create/SKILL.md b/skills/create/SKILL.md index 9cb2ff6..65e1744 100644 --- a/skills/create/SKILL.md +++ b/skills/create/SKILL.md @@ -6,7 +6,7 @@ when_to_use: Use when user says "create a project", "new flutter app", "start a argument-hint: what to create (e.g., "flutter app", "dart package") effort: low allowed-tools: Read Glob Skill -compatibility: Designed for Claude Code (or similar products with agent support) +compatibility: Designed for Claude Code and GitHub Copilot CLI (or similar products with agent support) --- # Create a new project @@ -17,10 +17,12 @@ Route project creation to the right companion plugin. Wingspan does not scaffold $ARGUMENTS +If the text above still shows a literal placeholder instead of your input (e.g., on GitHub Copilot CLI, which does not substitute it), use whatever the user wrote after the skill name instead. + **If the description above is empty:** 1. First, scan recommendation files (Step 1 below) to discover available project types. -2. Then use **AskUserQuestion tool**: +2. Then use the **AskUserQuestion tool** (GitHub Copilot CLI: `ask_user`): - **Question:** "What kind of project would you like to create?" - **Options:** Build the option list from the discovered companion plugins' descriptions, plus "Other" as the last option. @@ -50,7 +52,7 @@ Compare the user's project description against each recommendation's `plugin` na ## Step 3: Verify the plugin is installed -Check the available skills listed in the system-reminder in your conversation context for any skill prefixed with the matched plugin name (`:`). +Check the available skills in your conversation context for any skill from the matched plugin. Claude Code lists plugin skills in a system-reminder with a `:` prefix; GitHub Copilot CLI lists them under their bare names — there, match by skill name and description instead. If **no skills from that plugin are listed**, the plugin is not installed. Use **AskUserQuestion tool**: @@ -66,13 +68,20 @@ If the user chooses to install, output the following commands and **stop**: /plugin install ``` +On GitHub Copilot CLI, output these instead (`` is the marketplace's registered name — usually the repository name): + +```bash +copilot plugin marketplace add +copilot plugin install @ +``` + Tell the user to run these commands, then re-invoke `/create` with the same project description. **Do not proceed to Step 4.** ## Step 4: Find and invoke the plugin's project-creation skill -The available skills are listed in the system-reminder in your conversation context. Look for skills prefixed with the matched plugin name (`:`). Among those, find the skill whose name or description best indicates project creation (look for terms like "create", "scaffold", "new project", "generate", "init"). +Using the naming convention from Step 3, look through the available skills in your conversation context for skills from the matched plugin. Among those, find the skill whose name or description best indicates project creation (look for terms like "create", "scaffold", "new project", "generate", "init"). -Invoke it using the **Skill tool** with its fully qualified name (e.g., `my-plugin:scaffold-project`), passing the user's full project description as arguments. +Invoke it using the **Skill tool** with its name as it appears in your context (fully qualified, e.g. `my-plugin:scaffold-project`, on Claude Code), passing the user's full project description as arguments. - **No project-creation skill found for the plugin:** Inform the user the companion plugin is registered but does not provide a project-creation skill. Stop. - **If the skill invocation fails:** Surface the error to the user and suggest verifying the companion plugin is properly installed. diff --git a/skills/debrief/SKILL.md b/skills/debrief/SKILL.md index e58a9d4..05db791 100644 --- a/skills/debrief/SKILL.md +++ b/skills/debrief/SKILL.md @@ -5,7 +5,7 @@ description: Produces a structured post-incident analysis — timeline, root cau when_to_use: Use when user says "debrief", "post-mortem", "incident review", or "root cause analysis". argument-hint: incident description, PR/commit refs, or error context effort: high -compatibility: Designed for Claude Code (or similar products with agent support) +compatibility: Designed for Claude Code and GitHub Copilot CLI (or similar products with agent support) --- # Post-incident debrief @@ -18,6 +18,8 @@ Produce a structured, blameless debrief document after an incident, failed relea $ARGUMENTS +If the text above still shows a literal placeholder instead of your input (e.g., on GitHub Copilot CLI, which does not substitute it), use whatever the user wrote after the skill name instead. + **If the incident context above is empty, ask the user**: "What incident would you like to debrief? Describe what happened, link to relevant PRs/commits, or paste error logs." DO NOT proceed until you have a description from the user. @@ -26,7 +28,7 @@ DO NOT proceed until you have a description from the user. ### 1. Gather initial information -Use the **AskUserQuestion tool** to fill in gaps one question at a time. Adapt based on what the user already provided — skip questions whose answers are already clear from the incident context. +Use the **AskUserQuestion tool** (GitHub Copilot CLI: `ask_user`) to fill in gaps one question at a time. Adapt based on what the user already provided — skip questions whose answers are already clear from the incident context. **Key questions to resolve:** diff --git a/skills/elements-of-style/SKILL.md b/skills/elements-of-style/SKILL.md index f00e76e..c64fb57 100644 --- a/skills/elements-of-style/SKILL.md +++ b/skills/elements-of-style/SKILL.md @@ -3,7 +3,7 @@ name: elements-of-style user-invocable: false description: Applies Strunk's Elements of Style principles when writing or editing prose. when_to_use: Triggers on "write clearly," "edit for style," "improve writing," or tasks requiring clear, vigorous English — documents, emails, reviews. -compatibility: Designed for Claude Code (or similar products) +compatibility: Designed for Claude Code and GitHub Copilot CLI (or similar products) --- # Elements of Style diff --git a/skills/hotfix/SKILL.md b/skills/hotfix/SKILL.md index c65a5e0..265b8f1 100644 --- a/skills/hotfix/SKILL.md +++ b/skills/hotfix/SKILL.md @@ -5,7 +5,7 @@ description: Applies a minimal, targeted fix for emergency bugs — enforces rev effort: high argument-hint: bug description, issue link, or error message allowed-tools: Bash(rm -rf docs/hotfix-review/) -compatibility: Designed for Claude Code (or similar products with agent support) +compatibility: Designed for Claude Code and GitHub Copilot CLI (or similar products with agent support) --- # Hotfix — emergency fix workflow @@ -16,6 +16,8 @@ Apply a minimal, targeted fix fast. No brainstorm document, no plan document — $ARGUMENTS +If the text above still shows a literal placeholder instead of your input (e.g., on GitHub Copilot CLI, which does not substitute it), use whatever the user wrote after the skill name instead. + **If the bug description above is empty, ask the user**: "What's the bug? Paste a description, issue link, or error message." DO NOT proceed until you have a bug description. @@ -39,7 +41,7 @@ After the agent returns: 2. Identify the root cause (or the most likely candidate). 3. Summarize the root cause to the user in 2-3 sentences. -If the root cause is unclear after exploration, use **AskUserQuestion** to ask the user for additional context before proceeding. +If the root cause is unclear after exploration, use **AskUserQuestion** (GitHub Copilot CLI: `ask_user`) to ask the user for additional context before proceeding. ## Phase 2 — Branch @@ -109,6 +111,9 @@ The reduced agent set and their report names (``): | **@vgv-review-agent** | `vgv-review` | | **@test-quality-review-agent** | `test-quality-review` | +On GitHub Copilot CLI these agents are installed by the `vgv-wingspan` plugin and are +listed with a `vgv-wingspan:` prefix — match agents by name suffix. + If an agent fails, note it, continue with the other, and record the failure in the report header so the reduced review isn't silently halved. ### After reviews complete diff --git a/skills/hotfix/references/pr-template.md b/skills/hotfix/references/pr-template.md index 1820272..5e8560b 100644 --- a/skills/hotfix/references/pr-template.md +++ b/skills/hotfix/references/pr-template.md @@ -17,4 +17,4 @@ - Cherry-pick friendly: single commit on `hotfix/` - -Generated with [Claude Code](https://claude.com/claude-code) `/hotfix` +Generated with the [VGV Wingspan](https://github.com/VeryGoodOpenSource/vgv-wingspan) `/hotfix` skill diff --git a/skills/plan-technical-review/SKILL.md b/skills/plan-technical-review/SKILL.md index a37ec2f..a29a4b8 100644 --- a/skills/plan-technical-review/SKILL.md +++ b/skills/plan-technical-review/SKILL.md @@ -5,7 +5,7 @@ description: Reviews an externally-authored implementation plan for quality, VGV when_to_use: Use to review a plan you did not create with /plan — a hand-written plan or one from another tool. Triggers on "review the plan", "is this plan ready", "validate my plan", or "check the plan". argument-hint: path to plan file effort: high -compatibility: Designed for Claude Code (or similar products with agent support) +compatibility: Designed for Claude Code and GitHub Copilot CLI (or similar products with agent support) --- # Plan technical review @@ -14,7 +14,7 @@ Review a plan that was not created by `/plan`. `/plan` runs this same review inl creation, so use this skill for externally-authored plans — hand-written, from another tool, or from a teammate. -**Plan file:** `$ARGUMENTS` (if empty, ask the user for the plan path or pick the most recent file under `docs/plan/`). +**Plan file:** `$ARGUMENTS` (if empty, ask the user for the plan path or pick the most recent file under `docs/plan/`). If the text above still shows a literal placeholder instead of your input (e.g., on GitHub Copilot CLI, which does not substitute it), use whatever the user wrote after the skill name instead. ## Review @@ -24,7 +24,7 @@ findings to the plan inline, and resolves any scope-splitting recommendation. ## Handoff -After the review completes, use **AskUserQuestion** to present next steps: +After the review completes, use **AskUserQuestion** (GitHub Copilot CLI: `ask_user`) to present next steps: **Question**: "Technical review complete! What would you like to do next?" diff --git a/skills/plan/SKILL.md b/skills/plan/SKILL.md index a95d79d..a86d9c9 100644 --- a/skills/plan/SKILL.md +++ b/skills/plan/SKILL.md @@ -5,7 +5,7 @@ description: Turns high-level brainstorming and ideas into well-structured, acti when_to_use: Use when user says "plan this", "create a plan", "how should we implement", or "write an implementation plan". effort: high argument-hint: feature, bug fix, or improvement to plan -compatibility: Designed for Claude Code (or similar products with agent support) +compatibility: Designed for Claude Code and GitHub Copilot CLI (or similar products with agent support) --- # Create a new implementation plan (or bug fix) @@ -16,6 +16,8 @@ Transform feature descriptions, bug reports, or improvement ideas into well-stru $ARGUMENTS +If the text above still shows a literal placeholder instead of your input (e.g., on GitHub Copilot CLI, which does not substitute it), use whatever the user wrote after the skill name instead. + ### 0. Idea Refinement Check for brainstorm output first — before asking the user anything. @@ -29,7 +31,7 @@ A brainstorm is relevant if created within the last 7 days and its topic semanti | Brainstorms found | Feature description provided? | Action | |-------------------|------------------------------|--------| | One relevant | Yes | Read it, announce "Found brainstorm from [date]: [topic]", extract key decisions, proceed | -| One relevant | No | **AskUserQuestion**: "Plan this brainstorm?" — (Recommended) use it, or describe something different | +| One relevant | No | **AskUserQuestion** (GitHub Copilot CLI: `ask_user`): "Plan this brainstorm?" — (Recommended) use it, or describe something different | | Multiple relevant | Either | **AskUserQuestion**: list candidates, ask which to use | | None / not relevant | No | Ask: "What would you like to plan?" | | None / not relevant | Yes | Run /brainstorm to clarify the idea first | @@ -73,6 +75,8 @@ Run these agents in parallel to gather external information: - **@official-docs-research-agent**: Fetches and synthesizes official documentation for relevant frameworks, libraries, and APIs. - **@best-practices-research-agent**: Researches and synthesizes best practices for the project's technology stack, following VGV conventions first, then official documentation, and finally industry standards. +On GitHub Copilot CLI, plugin agents are listed with a `vgv-wingspan:` prefix — match agents by name suffix. + ##### 1.1.2. Consolidate research findings After all research steps complete, consolidate findings: diff --git a/skills/review/SKILL.md b/skills/quality-review/SKILL.md similarity index 89% rename from skills/review/SKILL.md rename to skills/quality-review/SKILL.md index 0e4f57f..60af1e5 100644 --- a/skills/review/SKILL.md +++ b/skills/quality-review/SKILL.md @@ -1,12 +1,12 @@ --- -name: review +name: quality-review user-invocable: true description: Runs quality review agents on demand — reviews code against VGV standards for architecture, tests, and simplicity, then writes one consolidated, numbered report. when_to_use: Use when user says "review this code", "review my code", "code review", "review", "check this code", or "review before merging". argument-hint: "[path/to/files/or/directories (optional)]" allowed-tools: Bash(*/scripts/detect-review-scope.sh) Bash(gh *) Bash(glab *) effort: high -compatibility: Designed for Claude Code (or similar products with agent support) +compatibility: Designed for Claude Code and GitHub Copilot CLI (or similar products with agent support) --- # Review code on demand @@ -19,6 +19,8 @@ numbered findings the user can act on by id. $ARGUMENTS +If the text above still shows a literal placeholder instead of your input (e.g., on GitHub Copilot CLI, which does not substitute it), use whatever the user wrote after the skill name instead. + ## Step 1 — Detect Scope Parse the review scope above for optional file paths or directories. @@ -39,11 +41,13 @@ Run the scope detection script: ${CLAUDE_SKILL_DIR}/scripts/detect-review-scope.sh ``` +If the path above appears unexpanded (e.g., on GitHub Copilot CLI, which does not substitute this variable), run the script from this skill's own `scripts/` directory instead. + - **If `SCOPE=branch`**: use the listed files as scope. The scope slug is the current branch name with `/` replaced by `-`. Announce scope summary (changed-file count, areas affected) and proceed to Step 2. - **If `SCOPE=default`**: tell the user "You're on ``. No branch diff - available." Use **AskUserQuestion**: "What would you like to review?" with options: + available." Use **AskUserQuestion** (GitHub Copilot CLI: `ask_user`): "What would you like to review?" with options: - **Specify files or directories**: accept paths; derive the slug from the first path as above. - **Review entire project**: no scope constraint; slug `project`. @@ -74,6 +78,9 @@ Default agents and their report names (``): | **@test-quality-review-agent** | `test-quality-review` | | **@code-simplicity-review-agent** | `code-simplicity-review` | +On GitHub Copilot CLI these agents are installed by the `vgv-wingspan` plugin and are +listed with a `vgv-wingspan:` prefix — match agents by name suffix. + **If an agent fails:** note it, continue with the successful agents, and record the failure in the report header and chat summary so the user knows the review is incomplete. Offer to retry. diff --git a/skills/review/references/file-findings-on-pr.md b/skills/quality-review/references/file-findings-on-pr.md similarity index 100% rename from skills/review/references/file-findings-on-pr.md rename to skills/quality-review/references/file-findings-on-pr.md diff --git a/skills/review/references/review-agent-instructions.md b/skills/quality-review/references/review-agent-instructions.md similarity index 100% rename from skills/review/references/review-agent-instructions.md rename to skills/quality-review/references/review-agent-instructions.md diff --git a/skills/review/references/review-consolidation.md b/skills/quality-review/references/review-consolidation.md similarity index 100% rename from skills/review/references/review-consolidation.md rename to skills/quality-review/references/review-consolidation.md diff --git a/skills/review/references/review-report-template.md b/skills/quality-review/references/review-report-template.md similarity index 100% rename from skills/review/references/review-report-template.md rename to skills/quality-review/references/review-report-template.md diff --git a/skills/review/scripts/detect-review-scope.sh b/skills/quality-review/scripts/detect-review-scope.sh similarity index 100% rename from skills/review/scripts/detect-review-scope.sh rename to skills/quality-review/scripts/detect-review-scope.sh diff --git a/skills/rebase/SKILL.md b/skills/rebase/SKILL.md index 863e131..02b3fe8 100644 --- a/skills/rebase/SKILL.md +++ b/skills/rebase/SKILL.md @@ -6,7 +6,7 @@ description: Rebases the current feature branch onto the base branch (main/maste when_to_use: Use when user says "rebase", "sync branch", or "update branch". allowed-tools: Bash(*/scripts/detect-base-branch.sh) Bash(git fetch *) Bash(git rebase *) Bash(git stash *) effort: low -compatibility: Designed for Claude Code (or similar products with git access) +compatibility: Designed for Claude Code and GitHub Copilot CLI (or similar products with git access) --- # Rebase onto base branch @@ -31,6 +31,8 @@ Detect the base branch: ${CLAUDE_SKILL_DIR}/scripts/detect-base-branch.sh ``` +If the path above appears unexpanded (e.g., on GitHub Copilot CLI, which does not substitute this variable), run the script from this skill's own `scripts/` directory instead. + If the script exits with an error, inform the user no base branch was found and stop. ### Check for uncommitted changes @@ -39,7 +41,7 @@ If the script exits with an error, inform the user no base branch was found and git status --porcelain ``` -If there are uncommitted changes, use **AskUserQuestion**: +If there are uncommitted changes, use **AskUserQuestion** (GitHub Copilot CLI: `ask_user`): **Question:** "You have uncommitted changes. Rebase requires a clean working tree. What would you like to do?" diff --git a/skills/refine-approach/SKILL.md b/skills/refine-approach/SKILL.md index 11cb213..c094cbd 100644 --- a/skills/refine-approach/SKILL.md +++ b/skills/refine-approach/SKILL.md @@ -4,7 +4,7 @@ user-invocable: true description: Reviews and refines brainstorm or planning documents before implementation. Identifies gaps, clarifies assumptions, and ensures the approach is sound. when_to_use: Use when user says "refine this", "review my approach", or "is this ready". argument-hint: path to document to refine -compatibility: Designed for Claude Code (or similar products with agent support) +compatibility: Designed for Claude Code and GitHub Copilot CLI (or similar products with agent support) --- # Refine Approach @@ -15,6 +15,8 @@ Improve brainstorm and/or planning documents through structured review. **Document path:** `$ARGUMENTS` +If the text above still shows a literal placeholder instead of your input (e.g., on GitHub Copilot CLI, which does not substitute it), use whatever the user wrote after the skill name instead. + **If `$ARGUMENTS` is non-empty**, treat it as the document path and proceed to `Step 2. Assess`. **If `$ARGUMENTS` is empty**, ask the user which document to review. Check `docs/brainstorm/` and `docs/plan/` for recent documents to suggest. diff --git a/skills/shared/references/clear-context-handoff.md b/skills/shared/references/clear-context-handoff.md index 912382b..204da51 100644 --- a/skills/shared/references/clear-context-handoff.md +++ b/skills/shared/references/clear-context-handoff.md @@ -16,3 +16,6 @@ Where: - `` — the verb for the next phase (e.g., "planning", "building") - `` — the skill to invoke (e.g., `plan`, `build`) - `` — the full path to the document produced in the current phase + +`/clear` and `/` work the same on Claude Code and GitHub Copilot CLI. The +forward-transition skills (`plan`, `build`) are slash-reachable on both hosts. diff --git a/skills/shared/references/drive-to-green.md b/skills/shared/references/drive-to-green.md index 3be4dca..cf82a95 100644 --- a/skills/shared/references/drive-to-green.md +++ b/skills/shared/references/drive-to-green.md @@ -27,6 +27,8 @@ Read the plugin's `hooks/recommendations/*.json`. A file participates only if it If more than one file matches, first match wins. Prefer the project's MCP analyzer and test tools over shell commands when they are available. +`verificationSkill` values use Claude Code's `plugin-name:skill-name` form. On hosts that list plugin skills under bare names (GitHub Copilot CLI), match the part after the `:`. + ## Step 2 — Drive to green - **Delegated** — invoke the companion skill and let it run its own verify-fix-rerun loop. Do not wrap it in a second loop of your own. diff --git a/skills/shared/references/file-findings-on-pr.md b/skills/shared/references/file-findings-on-pr.md index d91bc8d..0ec625e 100644 --- a/skills/shared/references/file-findings-on-pr.md +++ b/skills/shared/references/file-findings-on-pr.md @@ -19,8 +19,9 @@ Use **AskUserQuestion**: "Which findings should I file on the PR?" - **All** — every finding in the report. - **Critical + Important** — skip Suggestions. -- **Pick specific** — present the findings as one or more multi-select lists (batches of up to - four, by `FINDING-NN` id + title) and keep only the checked ones. +- **Pick specific** — present the findings as one or more multi-select lists (batched to the + question tool's option limit — four in Claude Code — by `FINDING-NN` id + title) and keep + only the checked ones. If the user picks none, stop. diff --git a/skills/shared/references/plan-review.md b/skills/shared/references/plan-review.md index 8f38215..fe8ff8a 100644 --- a/skills/shared/references/plan-review.md +++ b/skills/shared/references/plan-review.md @@ -15,6 +15,8 @@ Pass `` to each. Run all three concurrently: - **@vgv-review-agent** — review the plan for adherence to Very Good Engineering practices and project conventions. - **@plan-splitting-agent** — assess plan scope and report whether the work is too large for a single reviewable PR. +On GitHub Copilot CLI, plugin agents are listed with a `vgv-wingspan:` prefix — match by name suffix. + ## 2. Apply findings inline Fold the simplicity and VGV findings into the plan file directly — tighten scope, close diff --git a/skills/shared/references/review-consolidation.md b/skills/shared/references/review-consolidation.md index bbef99c..6ed502a 100644 --- a/skills/shared/references/review-consolidation.md +++ b/skills/shared/references/review-consolidation.md @@ -89,9 +89,9 @@ Index — never paraphrased. ## Step 6 — Acting on findings -Each calling skill defines its own post-review menu (`/review` is advisory and asks first; -`/build` and `/hotfix` fix before shipping). This section only fixes the shared vocabulary -those menus use. +Each calling skill defines its own post-review menu (`/quality-review` is advisory and asks +first; `/build` and `/hotfix` fix before shipping). This section only fixes the shared +vocabulary those menus use. - **By id** — the user references findings by id ("apply FINDING-01 and FINDING-03"). For each id, read the linked `raw/` report only when the one-line `fix` isn't enough; read only @@ -99,6 +99,6 @@ those menus use. - **By rule** — a rule id acts on a whole class ("fix every `tests/missing-test-file`", "ignore all `simplicity/inline-single-use`"). Apply the action to every finding sharing it. - **Commit trace** — when fixes are committed and the consolidated report is kept (as in - `/review`), reference the ids in the commit body, e.g. `Addresses FINDING-01, FINDING-03 + `/quality-review`), reference the ids in the commit body, e.g. `Addresses FINDING-01, FINDING-03 from review.` Skills that delete the report after acting (`/build`, `/hotfix`) fix findings in place and do not cite ids, since the report they would point to no longer exists.