Skip to content

feat: make skills portable across agent harnesses - #128

Merged
ryzizub merged 15 commits into
mainfrom
claude/vgv-wingspan-pr-230-1476f3
Sep 8, 2026
Merged

feat: make skills portable across agent harnesses#128
ryzizub merged 15 commits into
mainfrom
claude/vgv-wingspan-pr-230-1476f3

Conversation

@ryzizub

@ryzizub ryzizub commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

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.md per skill, no build step.

What changed

  • Codex sidecar at skills/<name>/agents/openai.yaml, holding interface.display_name and interface.short_description. Picker and UI metadata only, it does not reach the model prompt.
  • when_to_use folded into description. Only Claude Code read when_to_use, so every trigger phrase was dropped elsewhere. codex debug prompt-input advertises skills as - <name>: <description> and nothing else.
  • description is 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.
  • In-body fallbacks for $ARGUMENTS, AskUserQuestion, and the MCP tools. Each names its CLI equivalent, gated so it never fires where block-cli-workarounds.sh would deny the command.
  • CI validates every skill on each PR instead of only changed ones, because validate-references reads sibling files.
  • Three skill fixes the eval run surfaced: green-gate routing on a stalled loop, the material-theming base-unit snippet, i18n handling a wrong-approach request.

Verified

  • Installed into a real Codex CLI 0.153.4. Skills load and route, matching the schema Codex's own bundled skills use.
  • Evals 96/100 with-skill, sealed-baseline flat 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.
  • All 20 CI checks green. markdownlint and claude plugin validate clean.

Reviewer notes

The description trim initially cut one clause too many. green-gate lost "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.md and AGENTS.md now 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-skill enforces the 1024-character cap as an error rather than a warning. Both points are documented in CONTRIBUTING.md and AGENTS.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

  • New feature (feat)
  • Bug fix (fix)
  • Code refactor (refactor)
  • Documentation (docs)
  • CI change (ci)
  • Chore (chore)

Refs VeryGoodOpenSource/vgv-wingspan#230

@ryzizub
ryzizub requested a review from jorgecoca July 24, 2026 10:52
@ryzizub
ryzizub marked this pull request as ready for review July 24, 2026 15:34
@ryzizub
ryzizub requested a review from a team as a code owner July 24, 2026 15:34
@ryzizub ryzizub changed the title feat: cross-harness skill portability fallbacks feat: cross-harness skill portability for the open standard Jul 24, 2026
@ryzizub
ryzizub marked this pull request as draft July 27, 2026 09:03
@ryzizub
ryzizub force-pushed the claude/vgv-wingspan-pr-230-1476f3 branch 2 times, most recently from 50ca033 to 6da168d Compare August 4, 2026 13:51
ryzizub and others added 6 commits September 3, 2026 17:44
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
ryzizub force-pushed the claude/vgv-wingspan-pr-230-1476f3 branch from 5e4d548 to 5231f3d Compare September 3, 2026 15:46
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>
@ryzizub ryzizub changed the title feat: cross-harness skill portability for the open standard feat: portable skills for the Agent Skills open standard Sep 4, 2026
ryzizub and others added 5 commits September 4, 2026 13:38
…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>
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>
@ryzizub ryzizub changed the title feat: portable skills for the Agent Skills open standard feat: make skills portable across agent harnesses Sep 8, 2026
ryzizub and others added 2 commits September 8, 2026 10:48
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
ryzizub marked this pull request as ready for review September 8, 2026 09:50
@ryzizub
ryzizub merged commit 8998e55 into main Sep 8, 2026
20 checks passed
@ryzizub
ryzizub deleted the claude/vgv-wingspan-pr-230-1476f3 branch September 8, 2026 11:21
@vgvbot vgvbot mentioned this pull request Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants