Local-first deprecation intelligence for software repositories.
Any maintainer can cut a release by following this page. A release publishes four things that must agree on one version: the npm package evergreen-deprecation, the GitHub Action (arminazimi/evergreen@vX.Y.Z), the generated Claude and Codex plugin packages, and the bundled lifecycle registries inside the package. Publishing needs maintainer accounts, so releases are lane: maintainer work.
main with a clean working tree, and CI on main is green.evergreen-deprecation package on npm and push tags to the repository.Every gate must pass on the commit you will tag. None of them is optional.
| Gate | Command | What it proves |
|---|---|---|
| Full check | npm run check |
Build, Action bundle matches source, all tests including coverage floors in CI, plugin packages are in sync, plugin evals. This is what CI and npm publish (through prepack) run. |
| Coverage floors | npm run test:coverage |
Lines, branches, and functions stay above the floors in package.json. |
| Public corpus | npm run validate:public-repos |
Exact findings on every pinned public repository, and each detector’s precision above its floor in benchmarks/thresholds.json. Needs network. |
| Source freshness | npm run check:sources |
No rule is stale and no source has moved or disappeared. Needs network. Review anything it reports before releasing. |
| Package contents | npm pack --dry-run |
Only dist/src, examples, registry, schemas, and skills ship; registry/sources.lock.json does not. |
The last weekly runs of the corpus and source-freshness workflows should also be green. If either is red, fix or explain it before tagging.
Update the changelog. Draft the entries from conventional commits with npm run release:notes (or run the Release notes workflow, which uploads the same text), then write them into CHANGELOG.md:
node dist/tools/changelog.js --write X.Y.Z --date YYYY-MM-DD
Only feat, fix, and breaking commits become entries; docs, test, ci, and chore commits are left out. The command moves the hand-written Unreleased bullets into a new ## X.Y.Z - YYYY-MM-DD section, appends the generated bullets, and leaves an empty ## Unreleased above. Read the section, remove duplicates, and make each bullet a clear imperative sentence.
Bump the version. Run npm version X.Y.Z --no-git-tag-version, then regenerate everything derived from it:
npm run build:plugins
npm run build:action
This updates the plugin manifests and .mcp.json pins under plugins/ and .claude-plugin/marketplace.json, and rebuilds dist/action/index.js. Never edit those generated files by hand.
docs/GITHUB_ACTION.md show arminazimi/evergreen@vX.Y.Z; update them to the new tag. The host setups under examples/agents/ pin evergreen-deprecation@X.Y.Z (and the Gemini extension its version); a test fails until they match package.json. server.json (the MCP Registry description) carries the version twice; bump it with package.json, and a test fails until they agree.chore: release X.Y.Z through a pull request. Merge it once CI is green.Tag the merge commit. On main after the merge:
git tag -a vX.Y.Z -m "vX.Y.Z"
git push origin vX.Y.Z
Publish to npm. prepack runs npm run check again, so a broken tree cannot be published:
npm publish
Confirm with npm view evergreen-deprecation version and run npx evergreen-deprecation@X.Y.Z --help in an empty directory.
v1), as a force-updated lightweight tag pointing at the new release. Do not move it for a pre-1.0 version.npm run package:codex-plugin writes artifacts/evergreen-codex-plugin-<version>.zip; follow Codex submission to submit it. The Claude plugin is served from the repository marketplace, so the merged change in step 4 is its release; see Claude plugin.Lifecycle rules ship inside the npm package under registry/, so every package release carries the rules as of its commit. Between package releases, rules reach users through a signed data release.
Use this when rules change and you do not want to wait for a package release. The data in registry/ on main is what gets published, so merge the rule changes first and let CI pass.
npm run check, then npm run validate:public-repos and npm run check:sources as in the gates above.main with dry run on (the default). It builds the bundle twice and requires identical bytes, signs it, verifies the signature, and keeps the files as a workflow artifact without publishing anything. Note that signing writes an entry to the public Sigstore transparency log, even in a dry run.Tag. The tag must be data-v plus the date of the commit being released in UTC, with .N for a second bundle that day:
git tag -a data-v2026.10.16 -m "Lifecycle data 2026.10.16" <commit>
git push origin data-v2026.10.16
If the tag and the bundle’s version disagree the workflow stops and says which tag the commit needs.
evergreen-data-<version>.json, its .sigstore.json signature, and SHA256SUMS. On a clean machine, evergreen data update should report the new version, and evergreen data status should show cache and the signer identity.A data release does not change the npm package or the Action. If the data format itself changes, that needs a new schemaVersion, a package release that understands it, and a minimumEvergreenVersion in the bundle. See the decision record and Lifecycle data.
Decide by what has already been published, and prefer fixing forward.
git push origin :refs/tags/vX.Y.Z and git tag -d vX.Y.Z.npm unpublish, which is restricted for packages that have users. Publish a fixed patch release, then mark the bad one with npm deprecate evergreen-deprecation@X.Y.Z "Use X.Y.Z+1: <reason>".registry/ and release a patch. If the rule is actively harmful (it reports something that is not deprecated), release first and discuss afterwards.After any rollback, add a line to CHANGELOG.md explaining what happened and which version replaces the bad one.