jamesfredley opened a new pull request, #15805:
URL: https://github.com/apache/grails-core/pull/15805

   ## The Problem
   
   The app-facing Grails agent skills (`grails-developer`, `grails-8-upgrade`) 
live in `.agents/skills`, and applications have no versioned way to get them. 
The first version of this PR exposed them to the 
[SkillsJars](https://www.skillsjars.com) publisher, but that service clones the 
repository and deploys unvoted `com.skillsjars:*` artifacts to Maven Central 
itself, outside the ASF release process.
   
   ## The Fix
   
   Publish the skills ourselves, as part of the normal Grails release, in the 
SkillsJars jar format.
   
   - Each published skill gets its own Gradle project under `grails-skills/`:
     - `:grails-skills-developer` → `org.apache.grails.skills:grails-developer`
     - `:grails-skills-upgrade-guide-8` → 
`org.apache.grails.skills:grails-8-upgrade`
   - Each skill lives in the project that publishes it, at 
`grails-skills/<project>/skills/<skill>/`. `.agents/skills/<skill>/SKILL.md` 
becomes a symlink to it, the same pattern `.claude/skills` already uses, so 
agents such as OpenCode still find the skills where they look by default.
   - A new convention plugin, `org.apache.grails.buildsrc.agent-skills`, 
packages a project's `skills/` directories at 
`META-INF/skills/<githubSlug>/<skill>/`, the layout SkillsJars defines. It 
fails the build when a project has no skills, a skill has no `SKILL.md`, or a 
skill's frontmatter `name` differs from its directory.
   - The jars are published projects, so they are staged, signed, and voted on 
with every other Grails artifact, and `grails-bom` manages them (through 
`grails-base-bom`). An application declares them without a version and gets the 
skills for the Grails version it builds with.
   - The root build collects every `grails-skills-*` project into a new 
`skillProjects` category, alongside `cliProjects`, `docProjects` and the 
others, and publishes all of them. A new skill project only needs registering 
in `settings.gradle`, and the build can single out skill projects later.
   - Contributor-only skills (`gradle-developer`, `groovy-developer`, 
`hibernate-developer`, `java-developer`, `mono-repo-integration`, `test-fixer`, 
`violation-fixer`) stay unpublished.
   
   ## Consuming the skills
   
   Applications use the [SkillsJars Gradle 
plugin](https://github.com/skillsjars/skillsjars-gradle-plugin), which extracts 
skill jars from any group as of 0.1.0. This PR uses 0.1.3, which also includes 
the fix for skillsjars/skillsjars-gradle-plugin#10:
   
   ```groovy
   plugins {
       id 'com.skillsjars.gradle-plugin' version '0.1.3'
   }
   
   dependencies {
       skill 'org.apache.grails.skills:grails-developer'
       skill 'org.apache.grails.skills:grails-8-upgrade'
   }
   
   skillsjars {
       outputDir = layout.projectDirectory.dir('.agents/skills')
   }
   ```
   
   `./gradlew extractSkillsJars` then writes each skill to 
`.agents/skills/skillsjars__apache__grails-core__<skill>/`.
   
   - **No versions:** the Grails Gradle plugin applies the Grails BOM to every 
configuration, including `skill`, so the dependencies need no version. A build 
without the Grails plugin adds `skill platform(grails-bom)`.
   - **Grails 7:** applications still on Grails 7 declare the version 
explicitly. Verified on Grails 7.0.14 with Gradle 8.14.5 and JDK 17.
   - **Output directory:** the guide warns that `extractSkillsJars` empties the 
output directory and `clean` deletes it, so it should hold only extracted 
skills.
   - **Naming:** directories are named after the jar path rather than the 
skill. OpenCode keys skills by their frontmatter `name` and scans recursively, 
so it finds them.
   
   Before 0.1.3, the plugin's `packageSkillsJars` task required a `skills/` 
directory in any project that applies the `java` plugin, which broke every 
Grails application that only extracts skills 
(skillsjars/skillsjars-gradle-plugin#10). The fix 
(skillsjars/skillsjars-gradle-plugin#11) shipped in 0.1.3, so no workaround is 
needed.
   
   ## Testing
   
   - New `AgentSkillsPluginSpec` in build-logic (TestKit), 8 cases: the jar 
layout including supporting files, a `githubSlug` set after the plugin is 
applied, a removed skill being dropped from the next jar, and each validation 
failure. Mutation-checked: disabling the validation fails the three validation 
cases.
   - New checked-in example builds in `end-to-end`: `agent-skills`, a Grails 
application declaring the skills without versions, and 
`agent-skills-plain-build`, which names the BOM. Both apply the SkillsJars 
Gradle plugin 0.1.3 and resolve the published jars and BOM. Their spec asserts 
that exactly the published skills are extracted, byte-identical to the 
repository's skills, each declaring the expected `name`.
   - Built both jars and checked their layout: 
`META-INF/skills/apache/grails-core/<skill>/SKILL.md` plus `LICENSE`, `NOTICE`, 
and `sbom.json`. `grails-bom` now manages `grails-developer.version` / 
`grails-8-upgrade.version`.
   - Manually checked a Grails 7.0.14 app (Gradle 8.14.5, JDK 17) extracting 
`grails-8-upgrade` with SkillsJars plugin 0.1.3 and an explicit version, and 
`com.skillsjars:maven-plugin:0.0.7` extracting both jars.
   - `:grails-doc:publishGuide` renders the Agent Skills section and its 
cross-references.
   
   Refs #15454
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to