0096: Release the plugin boundary at the first unused version¶
Context and Problem Statement¶
The approved plugin boundary targeted 0.9.0. Before its pull request merged, another release workflow published core 0.9.0 from the existing architecture, including six legacy plugin artifact sets. The maintainer approved continuing with 0.9.1. Published identities must remain immutable, and plugins must reject a core without the new contracts.
Considered Options¶
- Advance the affected artifact identities to 0.9.1 (chosen).
- Reuse 0.9.0: would give one version incompatible payloads and cannot replace an existing PyPI upload.
- Hold the release: the maintainer authorized completing the approved scope.
Decision Outcome¶
Chosen option: core 0.9.1 is the first release of the approved plugin boundary, because 0.9.0 is already public.
- The release boundary and rollout references to 0.9.0 in ADRs 0094 and 0095 now target 0.9.1. Their recorded measurements remain historical observations of the candidate used at that time.
- No additional module extraction is included. Resource remains the only extracted built-in module. The standard composition includes Clock, Resource, Tailscale and the Heinzelmännchen theme with its soundscapes.
- Every migrated plugin requires
heinzel>=0.9.1,<0.10. Clock, Tailscale, Atlassian, GitHub, Google and Zoom advance their own artifact identities to 0.9.1. The other projects retain their independent, unpublished versions. - Official version tooling stages the reviewed candidate. Automatic release finalizes that candidate when its metadata version exceeds the highest canonical reachable release tag; otherwise conventional commits select the next version. A forced bump still advances the current metadata version. Existing tags and artifacts remain intact.
- Plugin checks install the candidate wheel, then the released wheel once available. Each plugin retains its own dependency lock, selected checks and release. Bootstrap compatibility pins are removed after publication.
- One shared
heinzel-plugins/release.ymlworkflow publishes through the main-onlypypienvironment. Each PyPI project grants that identity access separately. First-time registration may be serial where PyPI requires it; this does not couple subsequent plugin releases. No aggregate Python package or persistent publishing token replaces these independent artifacts. - Publish
app-v0.9.1/standard.jsononly after its provenance and fresh-install checks pass. Installation remains the approved clean-install boundary; ordinary subsequent updates preserve explicit plugin choices.
Consequences¶
- Good: consumers cannot silently install the legacy 0.9.0 implementation for the refactored plugin contracts.
- Good: independent plugin delivery and the reduced local feedback loop are retained.
- Bad: release notes must distinguish the new architecture from the immediately preceding 0.9.0 release.
Confirmation¶
tests/unit/release_version_test.py checks candidate finalization, ordinary version advancement and invalid
identities. The release-script integration checks exercise actual version-tool and tag behavior in disposable
repositories. Each owning plugin check validates its dependency lock and rejects an incompatible core artifact.
Planner tests select an arbitrary changed plugin and its declared contract consumers while selecting no core
build or test work. The composition workflow checks the four metadata-enrolled defaults in a fresh installation.
PyPI publisher grants and published release identities require observed verification during release review.