Add plugin manifests, validation workflows, and release assertions - #141
Open
jposluns wants to merge 2 commits into
Open
Add plugin manifests, validation workflows, and release assertions#141jposluns wants to merge 2 commits into
jposluns wants to merge 2 commits into
Conversation
Makes Clean Language installable as a Claude plugin without changing how it works as a skill. The zip and the plugin are independent channels over one source tree: the zip is built from cleanlanguage/ and flattened so SKILL.md sits at the archive root, while the plugin is the repository itself, with skills pointing at ./cleanlanguage in source. Nothing here touches cleanlanguage/, the published archive, or the site. .claude-plugin/plugin.json and .claude-plugin/marketplace.json at the root. plugin.json carries a $schema that resolves; marketplace.json carries none, because https://json.schemastore.org/claude-code-plugin-marketplace.json returns 404 and a URL that does not resolve is worse than an absent optional field. The marketplace entry sets no version: Claude Code always takes plugin.json's value, so a version here could be masked by a stale manifest. plugin-validate.yml gates pull requests on a pinned CLI. Two checks, because neither covers the other: validating the root reads marketplace.json and recurses into plugin.json through the source: './' entry, while the skill's own frontmatter is read only when the holding directory is named skills, so the skill is staged into one. --strict is load-bearing there, since a missing frontmatter block is a warning. No paths filter, so the check stays promotable to required without hanging forever-pending on unrelated pull requests. plugin-drift.yml runs the same checks weekly against the current release, to catch the false green a stale pin produces while readers install with current versions. It gates nothing. Its header records what it does not prove and that GitHub disables scheduled workflows after 60 days of repository inactivity. release-package.sh gains two assertions reading the git tree at HEAD like the rest of that script: plugin.json's version must equal the Version: line in SKILL.md, and marketplace.json's plugins[0].name must equal plugin.json's name. Version 2.1.261 was verified against all four positive and negative cases before being chosen as the pin.
My own assertion caught this before it could ship: the dry run simulates a synthetic next release by bumping the Version: line in SKILL.md but left plugin.json alone, so release-package.sh failed on a mismatch the dry run had created itself. That would have red-CI'd the release gate on every run. A real release bumps both together, which is what the assertion enforces, so the dry run now does the same and is a faithful simulation rather than a broken one. Both assertions are proved to fail on a deliberate mismatch: a wrong plugin.json version and a wrong marketplace plugins[0].name each fail with the expected message, and the tree was restored and re-verified green afterwards.
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.
Closes TODO 27.3 to 27.7. Makes Clean Language installable as a Claude plugin without changing how it works as a skill.
The zip and the plugin are independent channels over one source tree. The zip is built from
cleanlanguage/and flattened soSKILL.mdsits at the archive root, which is what makes one file work for Claude, ChatGPT, and Copilot Studio. The plugin is the repository itself, withskillspointing at./cleanlanguagein source. Nothing here touchescleanlanguage/, the published archive, the checksum, or the site.Manifests.
plugin.jsoncarries a$schemathat resolves;marketplace.jsoncarries none, because the marketplace schema URL returns 404 and a URL that does not resolve is worse than an absent optional field. The marketplace entry sets noversion: Claude Code always takesplugin.json's value, so a version here could be masked by a stale manifest.Validation.
plugin-validate.ymlgates pull requests on a pinned CLI. Two checks, because neither covers the other: validating the root readsmarketplace.jsonand recurses intoplugin.jsonthrough thesource: "./"entry, while the skill's own frontmatter is read only when the holding directory is namedskills, so the skill is staged into one.--strictis load-bearing there, since a missing frontmatter block is only a warning. No paths filter, so the check stays promotable to required without hanging forever-pending on unrelated pull requests.Drift.
plugin-drift.ymlruns the same checks weekly against the current release, catching the false green a stale pin produces while readers install with current versions. It gates nothing. Its header records what it does not prove, and that GitHub disables scheduled workflows after 60 days of repository inactivity.Release assertions.
release-package.shgains two, reading the git tree at HEAD like the rest of that script:plugin.json's version must equal theVersion:line inSKILL.md, andmarketplace.json'splugins[0].namemust equalplugin.json's name. Both are proved to fail on a deliberate mismatch.release-dry-run.shnow bumps the plugin version alongside the skill version, because a real release bumps both together and the dry run would otherwise fail on a mismatch it created itself.CLI version 2.1.261 was verified against all four positive and negative cases before being chosen as the pin.
All ten local gates pass, each run to a real exit code.
Not in this PR:
27.8, making these checks required onmain. Until that lands they are advisory, since only Cloudflare Pages is required today.