feat: make skills portable across agent harnesses - #128
Merged
Conversation
ryzizub
marked this pull request as ready for review
July 24, 2026 15:34
ryzizub
marked this pull request as draft
July 27, 2026 09:03
ryzizub
force-pushed
the
claude/vgv-wingspan-pr-230-1476f3
branch
2 times, most recently
from
August 4, 2026 13:51
50ca033 to
6da168d
Compare
Replicate the Phase 0 skill-portability work from VeryGoodOpenSource/vgv-wingspan#230 for this plugin: make skills degrade gracefully on non-Claude harnesses (Codex, Gemini CLI, OpenCode) via the Agent Skills open standard, without changing Claude Code behavior. - CI: validate every skill each run (list-skills) and add a frontmatter guard job (scripts/ci/check-frontmatter.sh) covering UTF-8 BOM detection and agents/**/*.md frontmatter, which no other check covers. - $ARGUMENTS literal-text fallbacks in very-good-analysis-upgrade and dart-flutter-sdk-upgrade. - AskUserQuestion fallbacks in accessibility and create-project, backed by a shared skills/shared/references/interaction-fallbacks.md symlinked into each consuming skill. - MCP graceful degradation: the dart / very-good-cli MCP tools fall back to the equivalent very_good / dart / flutter CLI off Claude Code (create-project, license-compliance, testing, layered-architecture, ui-package, flutter-reviewer). green-gate keeps its hook-enforced MCP-only mandate on Claude Code and only adds the off-Claude fallback. - CONTRIBUTING gains a Cross-harness portability section; CLAUDE.md structure block and cspell words updated. Refs VeryGoodOpenSource/vgv-wingspan#230 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Relocate check-frontmatter.sh from scripts/ci/ to .github/scripts/ so the CI-only helper lives alongside the workflow that runs it. Update the ci.yaml job command and the CONTRIBUTING references, and drop the scripts/ node from the CLAUDE.md structure tree (dotfile CI dirs are not enumerated there). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Match the CONTRIBUTING frontmatter guidance in VeryGoodOpenSource/vgv-wingspan#230: the spec's optional skills-ref linter rejects top-level fields outside the six it allows, and nesting the Claude Code extras under metadata: is the escape hatch if strict conformance is ever needed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reconcile with VeryGoodOpenSource/vgv-wingspan#230: name the non-Claude harnesses (Codex, Gemini CLI, OpenCode) the portability section targets, and state the full spec-conformance rules for the skill name field (kebab-case, no leading/trailing/consecutive hyphen, 1-64 chars, matches the directory). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Remove check-frontmatter.sh, its CI job, and its CONTRIBUTING references. The guard only added UTF-8 BOM detection plus frontmatter validation for the single agents/flutter-reviewer.md file; the 15 skills are already covered by validate-skill, so the extra script and CI job are not worth the machinery for one agent file. list-skills (validate every skill) stays. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
main moved the repository-structure tree from CLAUDE.md into AGENTS.md (#129). Re-home the two entries this branch adds — the shared interaction-fallbacks reference and its create-project symlink — into the AGENTS.md tree so the structure block stays in sync. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ryzizub
force-pushed
the
claude/vgv-wingspan-pr-230-1476f3
branch
from
September 3, 2026 15:46
5e4d548 to
5231f3d
Compare
Adopt three patterns from mattpocock/skills: - Codex sidecar: every skill ships agents/openai.yaml beside SKILL.md with interface.display_name + interface.short_description, so each skill carries its Codex skill-picker metadata without a build step. SKILL.md stays the single source of truth. - Invocation: every skill is model-invoked, so none sets disable-model-invocation or a Codex policy block; documented the user-invoked path (both flags, kept in sync) for any future human-only skill. - Own your references: drop the symlinked skills/shared/references/interaction-fallbacks.md and its two symlinks. The actionable guidance was already inlined in accessibility and create-project; the author-facing guidance now lives in CONTRIBUTING. No cross-folder symlinks, which do not survive every install path. Update CONTRIBUTING and AGENTS.md to match. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…lback The fallback assumed a host without AskUserQuestion has only plain text. Codex exposes request_user_input (currently gated to certain modes), so the guidance now says: use the host's own user-question tool where it has one, and fall back to plain numbered text only where neither exists. Updated the accessibility and create-project skill notes and the CONTRIBUTING section. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the Codex-specific naming. The fallback ladder is now host-agnostic: use AskUserQuestion on Claude Code, invoke whatever equivalent user-question tool the host provides elsewhere, and fall back to plain numbered text only when the host has none. Updated the accessibility and create-project notes and the CONTRIBUTING section. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review of this branch surfaced defects in the fallbacks it added. - Five CLI fallbacks fired on "MCP server not connected" alone, but block-cli-workarounds.sh denies those very commands and its Bash matcher is unconditional. On Claude Code with the VGV CLI missing, the MCP tool is denied and the shell fallback is denied too, so the note walked the model into a refused call. They now gate on the hook as well, matching green-gate's wording. - The license-compliance fallback named --licenses and --directory. Neither flag exists in Very Good CLI 1.3.0, so the command exited on a usage error before doing any work. The target path is positional, and --dependency-type is a multiOption defaulting to direct-main only, so transitive obligations (which this skill's Core Standards call out) needed it spelled out. Fixed here and at the pre-existing occurrence further down the file. - The ui-package fallback omitted the required <project-name>. - animation-testing.md linked ../../animations/SKILL.md, which the "Own your references" rule added by this branch forbids. Kept the pointer, dropped the link. - CONTRIBUTING claimed description carries the trigger phrasing; it lives in when_to_use, which only Claude Code reads. Corrected, and the sidecar paragraph no longer says frontmatter "cannot" carry a short description, since Codex reads metadata: short-description and the sidecar merely wins. - allowed-tools is optional and space-separated per the spec. Corrected the frontmatter table and example, and the one skill still using commas. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…i18n A full local eval run scored 97/100 in the with-skill column. Repeating each failing case 3x separated real weaknesses from the suite's noise, and each fix targets the guidance that did not reach the model rather than the case that caught it. - green-gate never mentioned a stalled loop in its routing inputs, so a prompt describing three identical rounds matched nothing and the skill was not invoked at all (1/3). Deciding when to stop and escalate is part of this loop, so both description and when_to_use now say so. It goes in description as well because only Claude Code reads when_to_use. - material-theming kept the base-unit multiplication only in references/spacing.md, so a model that never opened the reference emitted independent literals. The pattern is inline now, and the skill states that handing over the convention means writing the class out, since naming the steps in prose leaves the next arbitrary number free to be typed. - internationalization had the right guidance and example but never said what to do when asked for the wrong thing. Declining to put AppLocalizations in a shared package now comes with the rewritten widget and its call site as code. Verified 3x per case: green-gate 1/3 -> 3/3, material-theming 2/3 -> 3/3, internationalization 1/3 -> 3/3. Full suite 97 -> 100/100 with-skill, with sealed-baseline flat at 15/100 across all three runs, so the ablation still measures the plugin. layered-architecture-refuses-domain-model-in-data-layer also failed one run and was left alone: it repeats 3/3 and is noise. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e list The structure tree showed agents/openai.yaml only under accessibility, which reads as if that skill were special. All 15 ship one, so the note belongs on the skills/ node instead of on a single entry. The maintenance checklist also told you to sync a changed description with the README row while saying nothing about the sidecar, leaving its interface.short_description as a third copy nothing tracks. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
erickzanardo
approved these changes
Sep 4, 2026
Only Claude Code ever read when_to_use. Codex, Gemini CLI and OpenCode parse name and description and drop everything else, so the trigger phrasing that makes these skills findable never reached the harnesses this branch is meant to support. Verified directly: `codex debug prompt-input` advertises each skill as "- <name>: <description>", with when_to_use absent. All 15 descriptions now carry their own triggers and the field is gone. This is an editorial merge, not a concatenation: accessibility's when_to_use restated its description almost verbatim, and green-gate needed real cutting because its naive merge was 1809 characters against a hard 1024 cap that validate-skill enforces as an error. green-gate was already over Claude Code's 1536-character listing cap, so roughly 273 characters were being silently truncated before this. Two merges were corrected after a cross-set review: bloc had picked up "testing with blocTest and package:mocktail", which competes with a weight-3 testing routing assertion, and green-gate had compressed away "just re-check coverage" and "confirm the package is green", both quoted verbatim by an eval prompt. Costs, stated plainly: every description is concatenated into the Codex prompt on every request, so the skills block roughly doubles. static-security (995), dart-flutter-sdk-upgrade (992) and green-gate (989) now sit close to the ceiling, and adding a trigger to those three means trading one out. CONTRIBUTING and AGENTS.md say so. Full suite 98/100 with-skill, sealed-baseline flat at 15/100. The 15 negative controls all pass, which is the assertion that would catch widened descriptions stealing each other's routing. Both failures are routing misses that repeat clean: bloc 3/3, internationalization 2/3. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The three skills nearest the 1024 cap spent 80-150 characters each restating a rule their body already teaches: the caret convention, the green-gate exit condition, and the pen-testing scope note. Removing the duplicates reclaims 145-179 characters of headroom without touching a single trigger phrase. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cutting it as body-duplicated prose was wrong. Routing happens before the body loads, so the clause was the routing anchor for the case that measures "exit only on observed numbers", which fell 3/3 -> 1/3. Restored, back to 3/3, and green-gate still keeps 91 characters of headroom. Corrects the trimming guidance in CONTRIBUTING.md and AGENTS.md, which had recorded the same bad rule. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ryzizub
marked this pull request as ready for review
September 8, 2026 09:50
marcossevilla
approved these changes
Sep 8, 2026
Open
This was referenced Sep 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Makes the 15 skills load and route on non-Claude harnesses (Codex, Gemini CLI, OpenCode) via the Agent Skills open standard. Claude Code behavior is unchanged. One
SKILL.mdper skill, no build step.What changed
skills/<name>/agents/openai.yaml, holdinginterface.display_nameandinterface.short_description. Picker and UI metadata only, it does not reach the model prompt.when_to_usefolded intodescription. Only Claude Code readwhen_to_use, so every trigger phrase was dropped elsewhere.codex debug prompt-inputadvertises skills as- <name>: <description>and nothing else.descriptionis now triggers and scope only. Explanation belongs in the body, which has no cap. The three longest skills were each spending 80-150 characters restating a rule their body already taught, so the ceiling was self-inflicted.$ARGUMENTS,AskUserQuestion, and the MCP tools. Each names its CLI equivalent, gated so it never fires whereblock-cli-workarounds.shwould deny the command.validate-referencesreads sibling files.Verified
with-skill,sealed-baselineflat at 15/100 for the third run running, all 15 negative controls pass. Of the four failures, two routed correctly and missed output assertions, and the two routing misses repeat at 3/3 and 2/3, which is this suite's noise floor.claude plugin validateclean.Reviewer notes
The description trim initially cut one clause too many.
green-gatelost "exit only on observed numbers", on the reasoning that its body already taught the rule, and the case measuring exactly that fell from 3/3 to 1/3. Routing happens before the body loads, so the clause was a routing anchor rather than a duplicate. It is restored and back to 3/3, with 91 characters of headroom still reclaimed.CONTRIBUTING.mdandAGENTS.mdnow warn against that cut and require re-running a skill's evals after trimming its description.Length is a per-turn cost here, not just a lint rule. Every description is concatenated into the Codex prompt on every request, so the skills block roughly doubles.
validate-skillenforces the 1024-character cap as an error rather than a warning. Both points are documented inCONTRIBUTING.mdandAGENTS.md.Scoped out
Install path for the other harnesses. This repo publishes to none of them and the README makes no cross-harness claim.
Type of Change
feat)fix)refactor)docs)ci)chore)Refs VeryGoodOpenSource/vgv-wingspan#230